57727 sc medium venues with autostake long paymenttype can be griefed and cause permanent freeze of long token
Submitted on Oct 28th 2025 at 13:56:53 UTC by @iamephraim for Audit Comp | Belong
Report ID: #57727
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/periphery/Staking.sol
Impacts:
Permanent freezing of funds
Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)
Description
Brief/Intro
The Staking contract allows attackers to permanently lock LONG token by exploiting the stake array growth mechanism of any user. When venues enable autostake payment type, attackers can make thousands of tiny deposits to the venue's address, causing the stakes[venue] array to grow exponentially. This creates a gas exhaustion attack where withdrawal operations fail due to O(n) complexity, permanently freezing the venue's LONG tokens.
Vulnerability Details
The Staking contract contains an issue that allows attackers to permanently lock LONG token funds for venues using AutoStake functionality in its venue rules. The attack exploits the _deposit function's behavior of creating a new array entry for every deposit, regardless of size. An attacker can make thousands of tiny LONG token deposits (1 wei each) to a venue's address, causing the stakes[venue] array to grow at an exponential rate. This creates a gas exhaustion attack where any withdrawal attempt fails due to the O(n) complexity of _consumeUnlockedSharesOrRevert and _removeAnySharesFor functions. The victim becomes permanently locked out of their LONG token funds since even emergency withdrawals become gas-prohibitive. While venues are the primary target due to AutoStake venue rules, any user can be griefed through direct LONG token deposits.
The venue rules structure looks thus and available payment types:
/// @title LongPaymentTypes
/// @notice Venue-allowed Long payment options.
enum LongPaymentTypes {
NoType,
AutoStake,
AutoConvert
}
/// @title VenueRules
/// @notice Venue-level configuration for payment and bounty types.
struct VenueRules {
PaymentTypes paymentType;
BountyTypes bountyType;
LongPaymentTypes longPaymentType;
}Here are the functions involved for this attack path:
deposit() function which is made external from Solady's ERC4626 vault contract:
_deposit() function from the Belong's Stake contract that shows the stakes[venue] array and how attackers can grow the array exponentially with tiny LONG deposits:
_consumeUnlockedSharesOrRevert() function from the Belong's Stake contract that shows how a venue's stakes[venue] array is accessed and reduced:
_removeAnySharesFor():
Impact Details
This attack affects all stakers in the contract as any address can be targeted for griefing, not just venues with AutoStake. Attackers can make tiny deposits to any staker's address, causing their stake arrays to grow and making withdrawals impossible due to gas exhaustion.
Recommendations (summary): implement minimum deposit thresholds, array size limits per user, stake consolidation mechanisms, and gas-efficient withdrawal algorithms to prevent array manipulation attacks.
References
The vulnerable
depositfunction https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/periphery/Staking.sol#L245Public function to get venue rules -
generalVenueInfohttps://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/platform/BelongCheckIn.sol#L248Line showing the flow of LONG token from BelongCheckIn to Stake contract https://github.com/immunefi-team/audit-comp-belong/blob/a17f775dcc4c125704ce85d4e18b744daece65af/contracts/v2/platform/BelongCheckIn.sol#L486-L490
Proof of Concept
Gas Exhaustion in Normal Withdrawal
Venue attempts to withdraw their staked LONG token funds normally.
_withdraw()calls_consumeUnlockedSharesOrRevert()which loops through all array entries.The O(n) complexity causes gas exhaustion with 10,000+ entries.
Transaction fails due to gas limit; LONG token funds remain locked.
Emergency Withdrawal Also Fails
Venue attempts emergency withdrawal via
emergencyWithdraw()oremergencyRedeem().These functions call
_removeAnySharesFor()which also loops through the entire array.Same gas exhaustion occurs; emergency withdrawal fails.
Venue is completely locked out of their LONG token funds.
Was this helpful?