57201 sc low missing collection expiry enforcement

Submitted on Oct 24th 2025 at 10:38:54 UTC by @OxPrince for Audit Comp | Belongarrow-up-right

  • Report ID: #57201

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/immunefi-team/audit-comp-belong/blob/feat/cairo/src/nft/nft.cairohttps://github.com/immunefi-team/audit-comp-belong/blob/feat/cairo/src/nft/nft.cairo

  • Impacts:

    • Unauthorized minting of NFTs

Description

Brief/Intro

  • The NFT contract persists the collection_expires timestamp during initialization (src/nft/nft.cairo:140-147) and exposes it through the public nftParameters getter (src/nft/nft.cairo:181-183), signalling to integrators that the collection has an on-chain expiry.

  • Neither minting path (mintDynamicPrice / mintStaticPrice) nor their internal helpers ever read this field (src/nft/nft.cairo:254-347); there is also no alternate entry point that enforces the deadline.

  • As a result, any caller that obtained a valid mint signature before the advertised deadline can continue minting indefinitely after the sale should have closed, up to max_total_supply. This contradicts the intended lifecycle and misleads downstream integrations that rely on the expiry field.

Vulnerability Details

collection_expires is written to storage when the factory initializes a collection (src/nft/nft.cairo:140-147) and recorded in the factory flow as part of NftParameters (src/nftfactory/nftfactory.cairo:304-334).

  • The minting helpers _mint_dynamic_price_batch and _mint_static_price_batch only validate signatures, payment tokens, and prices before minting (src/nft/nft.cairo:254-347). They never consult collection_expires, nor is there any timestamp verification elsewhere in the contract.

  • Tests assert that collection_expires is returned from nftParameters() (src/tests/test_nft.cairo:189-207), reinforcing that the expiry is expected to be meaningful, yet no behavioural test exercises an expiry guard.

Impact Details

A buyer who received a valid pre-signed mint authorization (static or dynamic price) can wait until after the expected deadline and continue minting tokens as long as supply remains. This extends sales windows, defeats time-limited scarcity, and can lead to unexpected revenue splits or regulatory exposure for creators relying on time-boxed raises.

  • Because the expiry is stored on-chain and surfaced in the ABI, integrators are likely to treat it as authoritative.

References

Add any relevant links to documentation or code

Proof of Concept

The following PoC demonstrates a test that creates a collection with an expiry, waits past that expiry, and successfully mints using a pre-signed static-price authorization — showing expiry is not enforced.

chevron-righttest_mintStaticPrice_after_expiry_poc (Rust test + helper)hashtag

Notes for remediation (not exhaustive):

  • Enforce collection_expires in the minting paths by comparing current block timestamp to the stored expiry before accepting a signed mint.

  • Ensure both single and batch mint helpers consult the expiry.

  • Consider adding tests that assert minting fails after expiry for both static and dynamic flows.

Was this helpful?