Closed sherlock-admin3 closed 4 months ago
This issue is low (invalid) because it involves the loss of dust amounts of funds, which don't have any impact on the overall protocol behavior.
The issue causes loss of funds . at least sounds clear to me.
Even the claim is backed by PoC
Accumulation of small dust can lead to a big value causing a lot of miscalculations in the rates .
From the Sherlock guidelines:
The losses must exceed small, finite amount of funds, and any amount relevant based on the precision or significance of the loss.
Your PoC shows a loss of 1e4
assets, that is 0.000000000001%
of 1e18
. Even if an attacker repeats for millions of times this attack, losing gas fees, it wouldn't even be significant.
@santipu03 The issue doesn't even require an attacker; it's a recurring problem with every 'repayAtMaturity' transaction, which keeps growing indefinitely. Also, relying solely on 1e18 is not always applicable. WBTC has 8 decimals and a high value. This, for sure, will lead to insolvency in the future for an active pool .
The fact that #68 is valid with a proof of concept of an attacker iterating 20,000 times to steal $2400, ignoring the gas fees, and this, which grows indefinitely, not being valid, is weird .
If we consider that for every repayment of a fixed loan, 1 wei of assets can become stuck in the pool, this may become a problem in the long run for the WBTC pool. A user could maybe cause a grief attack on the WBTC pool by executing this attack in a loop but it wouldn't make much sense because the gas fees would be high and there's no profit on doing it.
The main difference between this issue and 68 is that there's no profit in executing an attack like this, and the damage is more limited than 68. However, I admit that this issue can be triggered organically, even though the impact will be much more limited because it'd need a ton of fixed loan repayments.
After reconsidering all the facts, I believe this issue is borderline low/medium. The head of judging will have the final say on this.
@elhajin This is a Low/Information severity issue. 1 wei is an extremely small value, even for 8 decimal tokens.
The attack vector you described in the issue is unrealistic, even for L2, where the gas is lower.
One transaction in optimism costs 0.1 gwei - https://tokentool.bitbond.com/gas-price/optimism
This is equal to 100000000 Wei. You can use this calculator to get an idea of how small 1 Wei is - https://eth-converter.com/
elhaj
high
Precision Loss in
repayAtMaturity
can lead to system insolvency and loss of fundsSummary
repayAtMaturity()
function can lead to a gradual insolvency in the protocol, resulting in potential losses for depositors.Vulnerability Detail
floatingBackupBorrowed
variable is critical for maintaining the protocol's solvency as it tracks the amount of assets borrowed from the floating pool by fixed pools. Accurate tracking is vital since it influences key financial operations such as debt calculations, withdrawal limits, and share pricing.floatingBackupBorrowed
. However, due to a rounding down issue in thescaleProportionally
function, there's a consistent precision loss of 1 wei. This discrepancy means that the borrower's principal is reduced by 1 wei more than the amount subtracted fromfloatingBackupBorrowed
andpool.borrowed
.scaleProportionally
andreduceProportionally
, both usingmulDivDown
for calculations, which rounds down the results. When repaying, theprincipalCovered
is calculated withscaleProportionally
, which underestimates by 1 wei. Then,reduceProportionally
is used to adjust the borrower's position, further reducing the principal by an additional wei due to rounding down.and then we reduce the amount
floatingBackupBorrowed
andpool.borrowed
by principal that we get from scaleProportionally function :reduceProportionally
which also rounds down :in this case we can alway reduce the user position by
1wei
more , Let's illustrate the precision loss issue with a step-by-step example:Initial state:
totalFloatingBorrowed = 1000 wei
.pool[1].borrowed = 1000 wei
,pool[1].supplied = 0 wei
.userA[1].principal = 1000 wei
,userA[1].fee = 100 wei
.User A decides to repay
100 wei
:Calculate
principalCovered
:scaleProportionally
:principalCovered = (100 wei * 1000 wei) / (1000 wei + 100 wei) = 90 wei
(rounded down).floatingBackupBorrowed
andpool[1].borrowed
:floatingBackupBorrowed = 1000 wei - 90 wei = 910 wei
.pool[1].borrowed = 910 wei
.Calculate User A's new position:
reduceProportionally
:1100 wei - 100 wei = 1000 wei
.userPrincipal = (1000 wei * 1000 wei) / 1100 wei = 909 wei
(rounded down).userA[1].fee = 1000 wei - 909 wei = 91 wei
.Discrepancy:
User A's
principal
is reduced by91 wei
, but thefloatingBackupBorrowed
andpool[1].borrowed
are only reduced by90 wei
.Each repayment results in User A's principal being decreased by
1 wei
more than the amount subtracted fromfloatingBackupBorrowed
andpool.borrowed
.This mismatch can lead to a growing discrepancy between the actual debt and the debt recorded by the protocol, potentially causing solvency issues.
The
reduceProportionally
function should use the sameprincipalCovered
value to avoid this precision loss.The precision loss issue, although seemingly minor,it can be exploited by a malicious user who repeatedly repays a debt in increments of
1 wei
. By creating a debt once and then partially repaying it, the user's principal is reduced by1 wei
more than what is subtracted fromfloatingBackupBorrowed
andpool.borrowed
. This can be repeated in a loop, with eachrepayAtMaturity
call , to slowly but consistently deplete the protocol's assets. On Layer 2 networks, where gas fees are lower, such an attack becomes more feasible, especially with assets likeWBTC
that have fewer decimals and higher value, making the attack more impactful over time.POC :
add this test :
Impact
floatingBackupBorrowed
will be locked forever in the contract even though it was paid it's not possible to withdraw it.floatingBackupBorrowed
, risking protocol insolvency.Code Snippet
Tool used
Manual Review
Recommendation
reduceProportionally
function to usemulDivUp()
for rounding up, ensuring consistency with thescaleProportionally
function which rounds down.