TokenTable · Smart Contract Security AssessmentTokenTable Client Hub

TokenTable Merkle Token Distributor

A co-audit by Zealynx Security and CODESPECT of the TokenTable Merkle Token Distributor, an EVM contract suite that manages airdrop and vesting distributions through Merkle proof verification. The 4-day review identified 4 issues across 620 SLOC: 1 Medium (locked NFTs in the ERC-721 distributor), 1 Low (upgrade permission scoped to the project owner), and 2 Informational. Two findings fixed, two acknowledged.

EthereumSoliditySmart Contract Code Review2025-04-28merkle-token-distributorZealynx methodology
Total findings
4
2 fixed · 2 acknowledged
Critical
00
High
00
Medium
01
Low + Info
03
02

Scope

8 files · 620 SLOC
Repository
Initial commit
96fedd0d9456
Final commit
0e4cd1d1c27d
Platform
Ethereum · Solidity
Methodology
File
core/MDCreate2.sol
core/BaseMerkleDistributor.sol
core/extensions/SimpleNoMintERC721MerkleDistributor.sol
core/extensions/TokenTableNativeMerkleDistributor.sol
core/extensions/CustomFeesNativeMerkleDistributor.sol
core/extensions/TokenTableMerkleDistributor.sol
core/extensions/SimpleERC721MerkleDistributor.sol
core/extensions/custom/NFTGatedMerkleDistributor.sol
03

Findings

click any row for the full write-up
04

Key Findings

  • Incorrect withdrawal implementation may lock unclaimed NFTs. In SimpleERC721MerkleDistributor, the withdraw() function attempts to transfer existing NFTs from the contract, but unclaimed NFTs are minted on demand rather than held by the contract. If minting permissions are scoped to the distributor and not the owner, the project team cannot recover unclaimed NFTs and they may be effectively lost.
  • Upgrade permission assigned to the project owner instead of TokenTable. The _authorizeUpgrade function in BaseMerkleDistributor is gated by the contract owner (the project team), not by TokenTable. A malicious project owner could upgrade the contract to a custom implementation that bypasses fee collection or redirects fees away from TokenTable.
  • NFT fee handling incompatible with BIPS-style fees. claimedAmount for ERC-721 distributions represents a small token count (e.g. 1 or 2). When the ITTUFeeCollector::getFee() formula multiplies by feeBips / BIPS_PRECISION, low values can round to zero, breaking BIPS-based fee policies for NFT distributions.
  • getClaimDelegate not blocked when delegated claiming is disabled. NFTGatedMerkleDistributor disables delegated claiming by reverting on setClaimDelegate, batchDelegateClaim, and delegateClaim, but getClaimDelegate remains callable. The inconsistency is purely surface-level but should be aligned for clarity.
05

Team & approval

Auditor
JecikPo
@JecikPo
Auditor
Carlos (Bloqarl)
@TheBlockChainer
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 (14p)
ZEALYNX SECURITY · published 2025-04-28
4 findings · Solidity

oog
zealynx

Smart Contract Security Digest

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

© 2026 Zealynx