F-2025-0016·off-by-one

Comparison in Unbonding Period Verification Forces Users to Wait Extra Block Before Claiming Tokens

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

claimUnstake uses strict > comparisons instead of >= for unbonding completion checks. The off-by-one extends the actual unbonding window by one block beyond what UNBONDING_PERIOD specifies.

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

Description

The LiquidStakingPool contract implements an incorrect condition check in the claimUnstake() function when verifying if unbonding periods have been satisfied. The function uses strict comparison operators (>) instead of inclusive comparison operators (>=), which extends the actual unbonding period by one block beyond what is intended.

solidity
uint256 blocksSinceRequest = block.number - request.requestBlock;
bool lspUnbondingComplete = (blocksSinceRequest > UNBONDING_PERIOD);
bool poolUnbondingComplete = (blocksSinceRequest > poolUnbondingPeriod);

When a user requests an unstake at block N with an unbonding period of X blocks:

  • At block N+X (when the period should complete), the condition X > X evaluates to false
  • Users can only claim at block N+X+1, extending the unbonding period by one block
03Section · Impact

Impact

This implementation error has the following impact:

  1. Users who attempt to claim their tokens exactly at the end of the unbonding period will have their transactions revert with UnbondingNotComplete(), even though the period has technically elapsed.
  2. The actual unbonding duration is extended by one block beyond what is specified by UNBONDING_PERIOD and poolUnbondingPeriod constants.

The issue affects all unstake claims in the protocol and represents a deviation from the intended functionality.

04Section · Recommendation

Recommendation

The comparison operators should be changed to inclusive comparisons to accurately reflect the intended unbonding period:

solidity
bool lspUnbondingComplete = (blocksSinceRequest >= UNBONDING_PERIOD);
bool poolUnbondingComplete = (blocksSinceRequest >= poolUnbondingPeriod);
F-2025-0016

oog
zealynx

Smart Contract Security Digest

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

© 2026 Zealynx