Closed sherlock-admin2 closed 2 months ago
PoC has wrong impact data
Escalate The POC showed the correct data. For a principal of 1,000,000, the interest generated in 1 second is 1, so the interest for one year is 31,557,600.
Escalate The POC showed the correct data. For a principal of 1,000,000, the interest generated in 1 second is 1, so the interest for one year is 31,557,600.
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
This should be invalid, from what i understand if an "attacker" continuously calls 'accrue()' all that will happen is them losing a lot of money at the cost of interest being compounded at a rate of block production.
This is exactly where I pointed out the problem: an ‘attacker’ can cause the pool’s interest to be far greater than 5%. The attacker doesn’t profit, but can cause losses for the borrower.
Although PoC works, there are many unknowns.
We'll take Polygon as an example, where gas is cheap: https://polygonscan.com/gastracker
Currently, one such transaction will cost around 0.25$.
A block in Polygon is 2 seconds, so he needs to call the function 15778800
times.
15,778,800 * 0.26 = $4,102,488
So, someone has to spend over 4 million dollars to inflate the interest rate on one of the cheapest networks.
This issue is no more than Low/Information severity.
Planning to reject the escalation and leave the issue as is.
Result: Invalid Unique
ZeroTrust
Medium
Accrued interest is calculated incorrectly due to a continuous griefing attack.
Summary
In the Arbitrum L2 environment, low transaction fees enable malicious users to exploit Pool::accrue() function, resulting in Accrued interest incorrect.
Vulnerability Detail
We can see that accrue can be called by any external user. The accrue() function calls accrue(pool, id), which internally calls simulateAccrue(). Ultimately, interest is calculated through the RateMode::getInterestAccrued() function.
Let’s take the FixedRateModel as an example to examine the getInterestAccrued function. Other RateModel implementations follow a similar pattern.
Since the internal calculations in getInterestAccrued use Math.Rounding.Up for approximations, this results in accrued interest being slightly higher than the actual interest. This issue becomes more pronounced for tokens like USDT and USDC, which have precision of 6 or lower. When subjected to continuous accrue() calls in a griefing attack, the problem can escalate, leading to an overestimation of interest.
POC
Assume the token is USDC, with a precision of 6, and the fixed annual interest rate is 5% (RATE = 5e16). The borrowed amount is 1,000,000.
Add the above function to ./test/core/Pool.t.sol and modify two values in the BaseTest.t.sol file.
Then run the command:
forge test --mt testTimeIncreasesDebtIncorrect -vv
This will produce the test result output.Thus, the actual generated annual interest rate is: 1*31557600/1000000 = 3155.76%, which is far greater than 5%.
Impact
The borrower ends up paying significantly more interest, leading to financial losses.
Code Snippet
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/Pool.sol#L375
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/Pool.sol#L401
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/Pool.sol#L380
https://github.com/sherlock-audit/2024-08-sentiment-v2/blob/0b472f4bffdb2c7432a5d21f1636139cc01561a5/protocol-v2/src/irm/FixedRateModel.sol#L30
Tool used
Manual Review
Recommendation
Add access control to the accrue function.