## 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 {
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);
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 {
if (fee == 0) {
return;
}
newExchangeRate = s_exchangeRate * (totalSupply() + fee) / totalSupply();
if (newExchangeRate <= s_exchangeRate) {
revert AssetToken__ExchangeRateCanOnlyIncrease();
}
}
```