Submitted by BowTiedOriole, also found by 0xJoyBoy03 (1, 2), pontifex, 0x0bserver, psb01, ReadyPlayer2, rouhsamad, CodeWasp, DanielArmstrong, n0kto, 0xpiken, Krace (1, 2), nuthan2x (1, 2), spark, kinda_very_good (1, 2), 0xlamide, pynschon, gesha17, MrPotatoMagic, Brenzee, Honour, DarkTower, turvy_fuzz, Fitro, shaflow2, Babylen, slippopz, d3e4, matejdb (1, 2), web3pwn, max10afternoon (1, 2), 0xAadi (1, 2), JohnSmith, miaowu, Myrault, krikolkk, TheSavageTeddy (1, 2), SovaSlava, atoko, Breeje, cryptphi, 0xlemon, SpicyMeatball, Tigerfrake, parlayan_yildizlar_takimi, csanuragjain, petro_1912, zhaojohnson, peanuts, and Fassi_Security
https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/main/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L214-L231
LiquidInfrastructureERC20._beforeTokenTransfer() checks if the to address has a balance of 0, and if so, adds the address to the holders array.
LiquidInfrastructureERC20#L142-145
However, the ERC20 contract allows for transferring and burning with amount = 0, enabling users to manipulate the holders array.
An approved user that has yet to receive tokens can initiate a transfer from another address to themself with an amount of 0. This enables them to add their address to the holders array multiple times. Then, LiquidInfrastructureERC20.distribute() will loop through the user multiple times and give the user more rewards than it should.
This also enables any user to call burn with an amount of 0, which will push the zero address to the holders array causing it to become very large and prevent LiquidInfrastructureERC20.distributeToAllHolders() from executing.
Adjust the logic in _beforeTokenTransfer to ignore burns, transfers where the amount is 0, and transfers where the recipient already has a positive balance.
Token Transfer
ChristianBorst (Althea) confirmed and commented:
