File: contracts/core/tokens/RToken.sol
317: function calculateDustAmount() public view returns (uint256) {
318: // Calculate the actual balance of the underlying asset held by this contract
- 319: uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this)).rayDiv(ILendingPool(_reservePool).getNormalizedIncome());
+ 319: uint256 contractBalance = IERC20(_assetAddress).balanceOf(address(this));
320:
- 321: // Calculate the total real obligations to the token holders
- 322: uint256 currentTotalSupply = totalSupply();
323:
324: // Calculate the total real balance equivalent to the total supply
- 325: uint256 totalRealBalance = currentTotalSupply.rayMul(ILendingPool(_reservePool).getNormalizedIncome());
+ 325: uint256 totalRealBalance = totalSupply();
326: // All balance, that is not tied to rToken are dust (can be donated or is the rest of exponential vs linear)
327: return contractBalance <= totalRealBalance ? 0 : contractBalance - totalRealBalance;
328: }
it("discovers bug in calculateDustAmount", async function () {
const rTokenInitialBalance = await rToken.balanceOf(user2.address);
const crvUSDInitialBalance = await crvusd.balanceOf(user2.address);
console.log("initial rToken balance =", ethers.formatEther(rTokenInitialBalance));
console.log("initial rToken balance (scaled) =", ethers.formatEther(await rToken.scaledBalanceOf(user2.address)));
expect(rTokenInitialBalance).to.equal(ethers.parseEther("1000"));
console.log("old liquidity index =", ethers.formatUnits(await lendingPool.getNormalizedIncome(), 27));
expect(await lendingPool.getNormalizedIncome()).to.equal(ethers.parseUnits("1", 27));
const tokenId2 = 2;
const amountToPay2 = ethers.parseEther("600");
await raacHousePrices.setOracle(owner.address);
await raacHousePrices.setHousePrice(tokenId2, amountToPay2);
await token.mint(user1.address, amountToPay2);
await token.connect(user1).approve(raacNFT.target, amountToPay2);
await raacNFT.connect(user1).mint(tokenId2, amountToPay2);
await raacNFT.connect(user1).approve(lendingPool.target, tokenId2);
await lendingPool.connect(user1).depositNFT(tokenId2);
const borrowAmount = ethers.parseEther("400");
await lendingPool.connect(user1).borrow(borrowAmount);
console.log("\nskipping time after borrow...\n");
await ethers.provider.send("evm_increaseTime", [365 * 24 * 60 * 60]);
await ethers.provider.send("evm_mine", []);
await lendingPool.connect(user2).updateState();
let newLiquidityIndex = await lendingPool.getNormalizedIncome();
console.log("new liquidity index =", ethers.formatUnits(newLiquidityIndex, 27));
expect(newLiquidityIndex).to.be.closeTo(ethers.parseUnits("1.025", 27), ethers.parseUnits("1", 18));
console.log("new rToken balance =", ethers.formatEther(await rToken.balanceOf(user2.address)));
console.log("new rToken balance (scaled) =", ethers.formatEther(await rToken.scaledBalanceOf(user2.address)));
expect(await crvusd.balanceOf(user2.address)).to.equal(crvUSDInitialBalance);
expect(await rToken.balanceOf(user2.address)).to.be.closeTo(ethers.parseEther("1025"), ethers.parseEther("1"));
await crvusd.mint(rToken.target, ethers.parseEther("500"));
console.log("dust amount in RToken contract =", ethers.formatEther(await rToken.calculateDustAmount()));
});
LendingPool
initial rToken balance = 1000.0
initial rToken balance (scaled) = 1000.0
old liquidity index = 1.0
skipping time after borrow...
new liquidity index = 1.025
new rToken balance = 1025.0
new rToken balance (scaled) = 1000.0
dust amount in RToken contract = 22.545731707317073171 ❌ <----- should have been 600 + 500 - 1025 = 75
✔ discovers bug in calculateDustAmount (117ms)
1 passing (7s)