Early rate$2,400 of senior audit time for $500. Early members keep the rate as it climbs.$2,400 of senior audit time for $500See how →
Matchain · Smart Contract Security AssessmentMatchain Client Hub

Matchain Liquid Staking Protocol

Zealynx audited Matchain's liquid staking protocol, the MAT token reward distribution mechanism with halving emissions, the pool ownership NFT, the staking pool factory, and the fee distribution vault. The 6-day review identified 23 issues including 6 High severity (two reentrancy windows around the pool ownership NFT transfer, halving boundary reward miscalculations, exchange rate front-running, and reward starvation beyond the first 21 pools). 18 findings were fixed during the engagement and 5 were acknowledged.

MatchainSoliditySmart Contract Code Review2025-07-11github.com/matchain/contractsZealynx methodology
Total findings
23
18 fixed · 5 acknowledged
Critical
00
High
06
Medium
05
Low + Info
12
02

Scope

7 files
Repository
Initial commit
50690f4ca1cf
Platform
Matchain · Solidity
Methodology
File
MATToken.sol
MatchConfig.sol
StakingPool.sol
LiquidStakingPool.sol
StakingPoolFactory.sol
PoolOwnership.sol
FeeDistributionVault.sol
03

Findings

click any row for the full write-up
Severity
ID
Finding
Status
highF-2025-0001Incorrect Halving Period Reward Calculation Leads to Significant Token Emission ReductionFixed›highF-2025-0002Exchange Rate Function Enables Direct Protocol Fee TheftAck›highF-2025-0003Reentrancy Vulnerability When Transferring Pool Tokens in PoolOwnership.solFixed›highF-2025-0004Reentrancy via Ownership Transfer Before Stake State Update in StakingPoolFixed›highF-2025-0005Incorrect Reward Rate Selection in Cross-Halving Distributions Causes Token UnderemissionFixed›highF-2025-0006Unrestricted Pool Creation Leads to Reward Starvation Beyond First 21 PoolsFixed›mediumF-2025-0007getCurrentBlockReward May Return Outdated Reward Due to Stale currentHalvingPeriodFixed›mediumF-2025-0008Integer Division Truncation in LiquidStakingPool Leads to Loss of User FundsFixed›mediumF-2025-0009Unclaimable Dust May Accumulate and Lock TokensAck›mediumF-2025-0010Incomplete fee accounting during pool migration leads to protocol revenue lossFixed›mediumF-2025-0011Integer Division Rounding in Reward Distribution Enables Malicious Reward Redirection and Protocol SabotageAck›lowF-2025-0012Missing call to _disableInitializers in several upgradeable contractsAck›lowF-2025-0013Potential Denial of Service Risk in FeeDistributionVault.sol Due to Unbounded LoopsFixed›lowF-2025-0014Missing stakers Counter Decrement in Ownership Transfer Leads to Inaccurate Staker AccountingFixed›lowF-2025-0015moveStakeToSelfStake Does Not Decrease stakers CountFixed›lowF-2025-0016Comparison in Unbonding Period Verification Forces Users to Wait Extra Block Before Claiming TokensFixed›lowF-2025-0017Inconsistent Share Calculation in calculateShareByAddress for the Last BeneficiaryFixed›lowF-2025-0018Incorrect Event Emitted in setPoolFactory FunctionFixed›lowF-2025-0019Use of blockhash(block.number) Returns Zero in generateSalt()Fixed›infoF-2025-0020Typo on file name FeeDistibutionVaultFixed›infoF-2025-0021Use of precomputed address to execute operations before actual deploymentAck›infoF-2025-0022Unused custom error in FeeDistributionVault reduces code clarity and increases gas costsFixed›infoF-2025-0023State updates in distribute() function deviate from CEI pattern best practicesFixed›
04

Key Findings

  • Reentrancy via ownership transfer before stake state update. The _transferOwnership function in StakingPool calls ownershipNFT.transferFrom (which fires onERC721Received) before updating the recipient's stake bookkeeping, opening a reentrancy window where the new owner controls the pool with a still-uncleared stake balance.
  • Reentrancy in pool token transfer. PoolOwnership.sol similarly calls super._safeTransfer before invoking moveStakeToSelfStake, letting a smart contract recipient observe the staking state mid-transfer and double-count or exploit it via onERC721Received.
  • Exchange rate function enables direct protocol fee theft. LiquidStakingPool.exchangeRate() is a public function that combines reading and state-modifying behaviour, so any address can front-run reward distribution with a no-cost exchangeRate() call to consume the reward delta and starve the protocol's fee accounting.
  • Halving boundary reward miscalculations. Two distinct High issues (IMM-HIGH-01 and IMM-HIGH-05) cause underemission across halving boundaries: the contract applies the post-halving reward rate to all blocks since the last distribution, yielding roughly 49% fewer tokens than the economic model intends.
  • Unrestricted pool creation leads to reward starvation beyond first 21 pools. Pool creation via mintPool is unbounded, but rewardDistribution only iterates over a fixed MAX_POOL_NUMBER = 21 pools, so any pool registered beyond the first 21 receives zero rewards regardless of stake.
05

Team & approval

Auditor
Zealynx Security Researchers
06

Disclaimer

This audit is not an endorsement and does not constitute investment advice. Zealynx reviewed the codebase at the commits listed in section 02 over the engagement window. Findings are limited to issues identified within that scope and do not preclude the existence of other vulnerabilities. Subsequent code changes are not covered by this report unless the engagement is explicitly extended.

Download PDF (81p)
ZEALYNX SECURITY · published 2025-07-11
23 findings · Solidity