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

1

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.

2

Unfairness and Broken Pro-Rata Principle

The bug breaks the fundamental promise of a pro-rata (proportional) yield distribution. Legitimate token holders are not receiving their mathematically fair share of the rewards, as a portion of their yield is consistently being redirected to another user.

References

https://github.com/plumenetwork/contracts/blob/main/arc/src/ArcToken.sol#L448-L457

Proof of Concept

Was this helpful?