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: 81/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
The _beforeTokenTransfer()
Implements the lock during distribution and adds to
to the list of holders when needed.
It checks if the recipient
(to)
already holds a balance
. If not, it adds the recipient
to the list of holders
. However, this approach might not be foolproof because a recipient could receive rewards meant for another holder
if they haven't been added to the list of holders yet.
function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual override { require(!LockedForDistribution, "distribution in progress"); if (!(to == address(0))) { require( isApprovedHolder(to), "receiver not approved to hold the token" ); } if (from == address(0) || to == address(0)) { _beforeMintOrBurn(); } @> bool exists = (this.balanceOf(to) != 0); if (!exists) { holders.push(to); } }
The line in question is:
bool exists = (this.balanceOf(to) != 0);
This line checks whether the recipient (to)
already holds a balance
of the token. If the balance is non-zero
, it implies that the recipient is already a holder
, and no action is taken. However, if the balance is zero
, it's assumed that the recipient is a new holder
, and they are added to the list of holders:
if (!exists) { holders.push(to); }
While this approach seems reasonable at first glance, it has a potential flaw: it assumes that any recipient not currently in the list of holders is indeed a new holder
.
However, this assumption may not always hold true. Here are some scenarios where this assumption might fail:
holder
transfers some of their tokens to themselves, the recipient (to)
will already be in the list of holders. However, because the balance check
only considers whether the balance is zero or not
, it will incorrectly assume that the recipient is a new holder
and attempt to add them to the list again.holder
receives tokens for the first time, but they haven't been explicitly added to the list of holders yet. In this case, the balance check will return zero
, and the recipient will be incorrectly identified as a new holder
, leading to their addition to the list.In both scenarios, the consequence is that the recipient might receive rewards that were actually intended for another holder
.
This discrepancy can potentially lead to inaccuracies in reward distribution and could undermine the fairness and integrity of the system
.
Manual Review
To mitigate this issue, a more robust approach to tracking holders and their balances could be implemented. This might involve maintaining a comprehensive list of all token holders and their corresponding balances, ensuring that each recipient is correctly identified and handled during transfers. Additionally, stricter validation could be enforced to verify the identity of recipients before distributing rewards to them.
Error
#0 - c4-pre-sort
2024-02-22T05:17:48Z
0xRobocop marked the issue as duplicate of #77
#1 - c4-judge
2024-03-04T13:16:16Z
0xA5DF marked the issue as satisfactory
#2 - c4-judge
2024-03-04T13:17:05Z
0xA5DF marked the issue as partial-50
#3 - c4-judge
2024-03-04T13:19:27Z
0xA5DF marked the issue as full credit
#4 - c4-judge
2024-03-08T14:36:31Z
0xA5DF marked the issue as satisfactory