F-2025-0017·view-mismatch

Inconsistent Share Calculation in calculateShareByAddress for the Last Beneficiary

Fixedliquid-stakinglststaking-poolsgithub.com/matchain/contracts
TL;DR

calculateShareByAddress uses (totalAmount * weight) / totalWeight uniformly for every beneficiary, but distribute() sweeps the rounding remainder into the last beneficiary. The view function returns a value that does not match the on-chain payout.

Severity
LOW
Impact
LOW
Likelihood
MEDIUM
Method
MManual review
CAT.
Complexity
LOW
Exploitability
LOW
02Section · Description

Description

The function calculateShareByAddress in FeeDistributionVault.sol calculates the share of a given beneficiary based on their weight relative to totalWeight:

solidity
(totalAmount * beneficiary.weight) / totalWeight;

However, this logic diverges from the actual distribution logic implemented in the distribute function, specifically for the last beneficiary.

In distribute, the remaining balance (remainingAmount = balance - distributedAmount) is transferred to the last beneficiary to avoid dust (small leftover tokens caused by rounding errors):

solidity
uint256 remainingAmount = balance - distributedAmount;
matToken.safeTransfer(beneficiaries[beneficiaries.length - 1].addr, remainingAmount);

As a result, when calculateShareByAddress is called for the last beneficiary, it may return a value that does not match what will actually be transferred during distribution.

This discrepancy can mislead frontends, indexers, or other off-chain systems relying on calculateShareByAddress to predict actual payout amounts. Specifically, the last beneficiary might see a computed value that underestimates or overestimates their real share.

03Section · Impact

Impact

Off-chain consumers display the wrong payout estimate for the last beneficiary in the list. The on-chain distribution is unaffected, but UIs and integrators may show stale or incorrect numbers.

04Section · Recommendation

Recommendation

Update calculateShareByAddress to mirror the behavior of distributing for the last beneficiary. This could involve:

  • Summing the calculated shares for all previous beneficiaries.
  • Returning totalAmount - sum(previousShares) for the last beneficiary.

This change will ensure consistency between the view logic and the actual on-chain distribution, eliminating confusion or mismatches in expected payouts.

F-2025-0017

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx