Summary
balanceIncrease
is not correctly calculated when mint DebtToken
.
Vulnerability Details
DebtToken
balance represents user's debt, when mint DebtToken
tokens, if _userState[onBehalfOf].index
is less than the usage index at the time of minting, balanceIncrease
is computed to reflect the accrued debt.
DebtToken.sol::mint()
uint256 amountScaled = amount.rayDiv(index);
if (amountScaled == 0) revert InvalidAmount();
uint256 scaledBalance = balanceOf(onBehalfOf);
bool isFirstMint = scaledBalance == 0;
@> uint256 balanceIncrease = 0;
@> if (_userState[onBehalfOf].index != 0 && _userState[onBehalfOf].index < index) {
@> balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
@> }
_userState[onBehalfOf].index = index.toUint128();
uint256 amountToMint = amount + balanceIncrease;
The problem is that balanceIncrease
is incorrectly calculated, DebtToken
overrides ERC20's _update()
and balanceOf()
.
In _update()
, user balance is stored as amount / index
in _balances[user]
.
DebtToken.sol::_update()
function _update(address from, address to, uint256 amount) internal virtual override {
if (from != address(0) && to != address(0)) {
revert TransfersNotAllowed();
}
uint256 scaledAmount = amount.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
super._update(from, to, scaledAmount);
emit Transfer(from, to, amount);
}
In balanceOf()
, user balance is returned as _balances[user] * index
.
DebtToken.sol::balanceOf()
function balanceOf(address account) public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledBalance = super.balanceOf(account);
return scaledBalance.rayMul(ILendingPool(_reservePool).getNormalizedDebt());
}
Therefore, in mint()
, balanceIncrease
is actually computed as amount / index0 * index1 * index1 - amount / index0 * index1 * index0
, that is, the value is wrongly multiplied by index
.
Impact
balanceIncrease
is wrongly calculated, user will bear more debt than expected.
Tools Used
Manual Review
Recommendations
The correct calculation should be:
- balanceIncrease = scaledBalance.rayMul(index) - scaledBalance.rayMul(_userState[onBehalfOf].index);
+ balanceIncrease = scaledBalance - scaledBalance.rayDiv(index).rayMul(_userState[onBehalfOf].index);