51525 sc low unfair yield distribution to last holder due to flawed dust handling
Submitted on Aug 3rd 2025 at 17:50:37 UTC by @rajaroy43 for Attackathon | Plume Network
Report ID: #51525
Report Type: Smart Contract
Report severity: Low
Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/arc/src/ArcToken.sol
Impacts:
Theft of unclaimed yield
Description
Brief/Intro
The distributeYield() function in the ArcToken.sol contract contains a flaw where it allocates all accumulated rounding errors (dust) from its pro-rata calculations to the single last holder processed in its distribution loop. This creates an exploitable economic vulnerability where a malicious actor can manipulate the order of token holders to consistently position themselves as the last recipient. This allows them to systematically siphon small but meaningful amounts of extra yield from the protocol, undermining the fairness of the entire distribution mechanism.
Vulnerability Details
The vulnerability stems from the combination of integer division and the method used to handle the resulting remainders. The distributeYield() function calculates each holder's share using a formula that truncates any remainder.
For every holder except the last one, the share is calculated as:
uint256 share = (amount * holderBalance) / effectiveTotalSupply;
This calculation is subject to precision loss. For example, if a user's true share is 332.9, they will only receive 332, and the 0.9 is left behind as "dust".
The code then attempts to account for this accumulated dust by giving the entire remaining amount to the final holder in the loop, using a different calculation:
// For the last holder: uint256 lastShare = amount - distributedSum;
Here, distributedSum is the sum of all the previously calculated (and rounded-down) shares. This means lastShare is equal to the last holder's own proportional share plus all the dust left over from every other holder's calculation.
This is exploitable because the order of elements in OpenZeppelin's EnumerableSet is not random. An attacker who understands the insertion and removal mechanics can perform actions to ensure their address is the last one in the holders array just before a distribution is triggered, thus guaranteeing they receive the extra funds.
Impact Details
Systematic Value Drain
A sophisticated and determined attacker can repeatedly exploit this flaw across multiple distribution cycles. This allows for a consistent, low-level drain of funds from the protocol. Over time, this can accumulate into a significant amount of value being unfairly diverted to the attacker instead of being retained by the protocol or distributed fairly.
References
https://github.com/plumenetwork/contracts/blob/main/arc/src/ArcToken.sol#L448-L457
Proof of Concept
Was this helpful?