Summary
Inside the DebtToken's implementation we can see that balanceOf(user) returns the user's balance multiplied by the lending pool's usageIndex which is also stated in the comment above it.
* @notice Returns the scaled debt balance of the user
* @param account The address of the user
* @return The user's debt balance (scaled by the usage index)
*/
function balanceOf(address account) public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledBalance = super.balanceOf(account);
return scaledBalance.rayMul(ILendingPool(_reservePool).getNormalizedDebt());
}
DebtToken.sol#223
Vulnerability Details
The problem is that totalSupply() actually divides the total supply by the lending pool's usageIndex which makes it return less than expect. This is further verified by the comment above the function.
* @notice Returns the scaled total supply
š * @return The total supply (scaled by the usage index)
*/
function totalSupply() public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledSupply = super.totalSupply();
š return scaledSupply.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
}
DebtToken.sol#232
Impact
With this current implementation totalSupply() will always be less than the sum of all user's balanceOf(user) which creates an inconsistency though the protocol.
Proof Of Concept
Click to reveal PoC
Place the following test case in LendingPool.test.js below describe("Borrow and Repay":
it.only("should showcase DebtToken inconsistency", async function () {
let totalSupply = await debtToken.totalSupply();
let balance = await debtToken.balanceOf(user1.address);
expect(totalSupply).to.equal(0);
expect(balance).to.equal(0);
ā
const borrowAmount = ethers.parseEther("25");
await lendingPool.connect(user1).borrow(borrowAmount);
ā
totalSupply = await debtToken.totalSupply();
balance = await debtToken.balanceOf(user1.address);
ā
console.table({ totalSupply, balance });
ā
expect(totalSupply).to.be.lt(borrowAmount);
});
Recommendation
Instead of dividing the total supply by the usage index, it should be multiplied by it.