Platform: Code4rena
Start Date: 13/02/2024
Pot Size: $24,500 USDC
Total HM: 5
Participants: 84
Period: 6 days
Judge: 0xA5DF
Id: 331
League: ETH
Rank: 82/84
Findings: 1
Award: $7.18
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedOriole
Also found by: 0x0bserver, 0xAadi, 0xJoyBoy03, 0xlamide, 0xlemon, 0xpiken, Babylen, Breeje, Brenzee, CodeWasp, DanielArmstrong, DarkTower, Fassi_Security, Fitro, Honour, JohnSmith, Krace, MrPotatoMagic, Myrault, ReadyPlayer2, SovaSlava, SpicyMeatball, TheSavageTeddy, Tigerfrake, atoko, cryptphi, csanuragjain, d3e4, gesha17, kinda_very_good, krikolkk, matejdb, max10afternoon, miaowu, n0kto, nuthan2x, parlayan_yildizlar_takimi, peanuts, petro_1912, pontifex, psb01, pynschon, rouhsamad, shaflow2, slippopz, spark, turvy_fuzz, web3pwn, zhaojohnson
7.1828 USDC - $7.18
An analysis of the provided Solidity code, which is part of a token contract implementing mechanisms for before and after token transfers and distribution of rewards, reveals a critical vulnerability. The vulnerability arises due to the lack of handling zero-value transfers in the _beforeTokenTransfer
function. This oversight allows a scenario where an address can be added to the holders
array without actually receiving any tokens, leading to potential denial of service (DoS) in the distribution function.
This vulnerability can be exploited to perform a DoS attack on the distribute
function. An attacker could repeatedly execute zero-value transfers to different addresses, adding numerous addresses to the holders
array without these addresses actually holding any tokens. When the distribute
function is called, it attempts to distribute rewards based on the faulty holders
list, leading to a failure (ERC20: transfer amount exceeds balance
) because the contract tries to distribute tokens to addresses without a proper balance. This not only prevents the distribution of rewards to legitimate holders but can also deplete the contract's resources and block the functionality of token distribution.
amount == 0
) from a holder (e.g., Alice) to various addresses (e.g., Eve) that do not currently hold any tokens.
holders
array.distribute
function to initiate the distribution process.
holders
array, including addresses added through zero-value transfers.>>> liquidierc.holders(0) == alice True >>> liquidierc.holders(1) == bob True >>> liquidierc.holders(2) File "<console>", line 1, in <module> File "brownie/network/contract.py", line 1901, in __call__ return self.call(*args, block_identifier=block_identifier, override=override) File "brownie/network/contract.py", line 1700, in call raise VirtualMachineError(e) from None VirtualMachineError: revert >>> liquidierc.transfer(alice_second_account, 0, {'from': alice}) Transaction sent: 0xb844ab68d8200331a2cf737a8a0ed0ff3c4dd64686498eba0b3503c7f864e37e Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 1 LiquidInfrastructureERC20.transfer confirmed Block: 11 Gas used: 62486 (0.52%) <Transaction '0xb844ab68d8200331a2cf737a8a0ed0ff3c4dd64686498eba0b3503c7f864e37e'> >>> liquidierc.transfer(alice_second_account, liquidierc.balanceOf(alice), {'from': alice}) Transaction sent: 0x7848b0aa7c0eceec34e23c03a0ab6667b9a27b645039dfab8d932a2b0955bcff Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 2 LiquidInfrastructureERC20.transfer confirmed Block: 12 Gas used: 68550 (0.57%) <Transaction '0x7848b0aa7c0eceec34e23c03a0ab6667b9a27b645039dfab8d932a2b0955bcff'> >>> liquidierc.holders(0) == alice_second_account True >>> liquidierc.holders(2) == alice_second_account True >>> liquidierc.distribute(5, {'from': bob}) Transaction sent: 0x255bbf7ac083a5d1da230e8594b9924b19fc567a8ab69c295af0518a74a2f759 Gas price: 0.0 gwei Gas limit: 12000000 Nonce: 0 LiquidInfrastructureERC20.distribute confirmed (ERC20: transfer amount exceeds balance) Block: 13 Gas used: 225936 (1.88%) <Transaction '0x255bbf7ac083a5d1da230e8594b9924b19fc567a8ab69c295af0518a74a2f759'>
Manual code review
Check for Zero-Value Transfers: Modify the _beforeTokenTransfer
function to include a check that prevents adding addresses to the holders
array during zero-value transfers. This can be achieved by adding an additional condition to ensure that the amount
being transferred is greater than zero.
DoS
#0 - c4-pre-sort
2024-02-20T06:35:51Z
0xRobocop marked the issue as duplicate of #77
#1 - c4-judge
2024-03-04T13:07:17Z
0xA5DF marked the issue as satisfactory