Thunder Loan

AI First Flight #7
Beginner FriendlyFoundryDeFiOracle
EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

updateExchangeRate Requires Strictly Increasing Exchange Rate — Zero-Fee Flash Loans Cause Revert

Root + Impact

Description

  • Describe the normal behavior in one or more sentences

  • Explain the specific issue or problem in one or more sentences

// Root cause in the codebase with @> marks to highlight the relevant section# [M-#] `updateExchangeRate` Requires Strictly Increasing Exchange Rate — Zero-Fee Flash Loans Cause Revert
## Summary
The `AssetToken.updateExchangeRate` function enforces a strict requirement that the newly calculated exchange rate must be strictly greater than the current exchange rate. If a flash loan is executed with a transaction parameter or pricing condition that yields a `fee` value of `0`, the calculated exchange rate remains unchanged. This causes a structural equality check to trigger an internal error, reverting the entire execution flow.
## Vulnerability Details
In `AssetToken.sol`, the function contains the following state validation step:
```solidity
newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();
if (newExchangeRate <= s_exchangeRate) {
revert AssetToken__ExchangeRateCanOnlyIncrease();
}
```
When a flash loan transaction processes where `fee == 0` (which occurs during small transaction amounts, asset pricing anomalies, or extreme down-rounding conditions), the equation evaluates as:
$$\text{newExchangeRate} = \frac{\text{s\_exchangeRate} \times \text{totalSupply()}}{\text{totalSupply()}} = \text{s\_exchangeRate}$$
Because `newExchangeRate` is exactly equal to `s_exchangeRate`, the `<=` comparison conditional validates as true. The contract immediately throws the `AssetToken__ExchangeRateCanOnlyIncrease` custom error and rolls back the transaction state. This blocks zero-fee or rounding-susceptible flash loan executions from terminating successfully.
## Impact
**Medium.** Legitimate flash loan operations are denied service whenever market oracle pricing or transaction sizing scales the fee metric down to zero. Attackers can exploit this logic to intentionally craft tiny or zero-value operational requests that force integrations or cross-protocol calls to revert dynamically.
## Proof of Concept
Add the following test case to your suite to confirm the zero-fee execution breakdown:
```solidity
function test_PoC10_UpdateExchangeRate_RevertsOnZeroFee() public {
// 1. Initialize AssetToken and seed standard liquidity supply
AssetToken at = new AssetToken(address(this), IERC20(address(token)), "AT", "AT");
token.mint(address(this), 1000e18);
at.mint(address(this), 1000e18);
token.transfer(address(at), 1000e18);
// 2. Invoke updateExchangeRate directly with a zero fee parameter
// The transaction systematically fails under the strict increase enforcement
vm.expectRevert(AssetToken__ExchangeRateCanOnlyIncrease.selector);
at.updateExchangeRate(0);
}
```
## Tools Used
* Manual Code Review
## Recommendations
Implement an early return conditional at the beginning of `updateExchangeRate` to safely bypass validation constraints if no protocol fees are collected:
```solidity
function updateExchangeRate(uint256 fee) external onlyThunderLoan {
// @audit-issue Bypasses strict check adjustments if zero fees are processed
if (fee == 0) {
return;
}
// ... existing logic
newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();
if (newExchangeRate <= s_exchangeRate) {
revert AssetToken__ExchangeRateCanOnlyIncrease();
}
}
```

Risk

Likelihood:

  • Reason 1 // Describe WHEN this will occur (avoid using "if" statements)

  • Reason 2

Impact:

  • Impact 1

  • Impact 2

Proof of Concept

Recommended Mitigation

- remove this code
+ add this code
Updates

Lead Judging Commences

ai-first-flight-judge Lead Judge 1 day ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!