57723 sc medium signature replay front run and timing control issues

Submitted on Oct 28th 2025 at 13:14:49 UTC by @koko7 for Audit Comp | Belongarrow-up-right

  • Report ID: #57723

  • Report Type: Smart Contract

  • Report severity: Medium

  • Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/platform/BelongCheckIn.sol

  • Impacts:

    • Permanent freezing of NFTs

    • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

    • Permanent freezing of funds

    • Block stuffing

Description

Brief/Intro

Multiple Belong protocol entry points accept platform‑signed payloads that are not bound to the caller, have no nonces/deadlines, and omit contract domain separation. As a result, valid signatures can be replayed by any address: customers can be repeatedly charged (Critical), venues can be forced to deposit repeatedly (High), AccessToken creation can be front‑run to squat collection names (High), and promoter payouts can be executed earlier than intended by anyone (Medium). In production, this leads to unauthorized spend, branding DoS, and operational griefing.

Vulnerability Details

  • Critical — payToVenue replay (USDC path)

    • Signatures validated here exclude msg.sender, have no nonce/deadline, and omit verifyingContract:

      Then funds are pulled from the customer each time the signed payload is replayed:

  • High — venueDeposit replayable forced spend

    • Venue signatures lack caller binding, nonce/deadline, and domain separation:

      On success, venueDeposit pulls USDC from the venue, applies fees, and mints credits; replaying the same signature re‑executes the spend as long as allowance remains.

  • High — Factory produce front‑run (name+symbol)

    • AccessToken creation signatures cover only (name, symbol, contractURI, feeNumerator, chainid) and are not bound to the intended creator:

      Factory uses (name, symbol) salt and msg.sender as creator. The first submitter with a valid signature wins; others hit TokenAlreadyExists():

  • Medium — promoter payouts timing control

    • Payout signatures are caller‑agnostic, lack nonce/deadline, and omit domain separation:

      Anyone can execute payouts early; credits are burned to prevent double‑spend, but timing is attacker‑controlled.

  • Informational (shared concerns)

    • abi.encodePacked with multiple strings → ambiguity risk; use EIP‑712 typed data.

    • No nonces/deadlines across signed flows → replayable.

    • No contract address in domain → potential cross‑app replay if the same signer key is reused.

Impact Details

  • Critical (payToVenue)

    • Unauthorized, repeated USDC transfers from customer to venue up to allowance/balance; likely large impact due to common infinite allowances.

  • High (venueDeposit)

    • Forced repeated deposits from venue to escrow; fees/credits re‑applied; spend controlled by attacker while allowance exists.

    • Branding/availability DoS: attacker squats collection (name, symbol); legitimate deployer is blocked by TokenAlreadyExists().

  • Medium (promoter payouts)

    • Payout timing controlled by anyone; automation can be griefed; operational/financial mismatches may occur (though double‑spend is prevented by credit burn).

References

  • Signature checks: contracts/v2/utils/SignatureVerifier.solcheckCustomerInfo, checkVenueInfo, checkAccessTokenInfo, checkPromoterPaymentDistribution

  • Execution sites: contracts/v2/platform/BelongCheckIn.solpayToVenue, venueDeposit, distributePromoterPayments

  • Factory creation: contracts/v2/platform/Factory.solproduce

  • Reproducer tests: test/v2/security/signature-replay.test.ts

Proof of Concept

  • create a test file: test/v2/security/signature-replay.test.ts

  • Run command (uses mainnet fork and dummy env vars for config):

  • Sample logs from a passing run:

Provided below is the full reproducer test used in the report (unchanged). It demonstrates replay of customer signatures, replayable venue deposits, factory front-running, and promoter payout timing control.

Was this helpful?