57610 sc medium venues can steal from customers by replaying payments via belongcheckin paytovenue
Submitted on Oct 27th 2025 at 15:39:22 UTC by @blackgrease for Audit Comp | Belong
Report ID: #57610
Report Type: Smart Contract
Report severity: Medium
Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/platform/BelongCheckIn.sol
Impacts:
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Affected Files: BelongCheckIn.sol
The BelongCheckIn contract coordinates venue deposits, customer check-ins and promoter settlements. The BelongCheckIn::payToVenue function processes a customer's payment to a venue.
The payment logic is gated: a Signer address must sign message input parameters before a payment proceeds — specifically the fields in the CustomerInfo struct: paymentInUSDC, visitBountyAmount, spendBountyPercentage, customer, venueToPayFor, promoter, amount, block.chainid.
However, once signed, payToVenue does not enforce logic to:
prevent repeating a signed payment to the same venue,
control who can call/execute
payToVenue.
As a result, if a user has approved the BelongCheckIn contract for USDC or LONG, a venue can replay the signed message and drain more funds than the intended single payment.
Below are two exploitation scenarios (USDC used as the payment method).
Scenario 1:
A victim has a balance of 5000 USDC and has 3 venue payments to make.
Venue_A requires 500 USDC, Venue_B requires 2500 USDC, Venue_C requires 2000 USDC. All inputs are signed by the Signer.
The victim approves the BelongCheckIn contract for 5000 USDC.
The victim makes the initial payment to Venue_A.
Because payToVenue does not:
check the caller, and
enforce a nonce preventing replay, Venue_A can call/frontrun the victim's following
payToVenuecalls repeatedly until the user's balance is depleted.
Venue exits with the user's funds causing user loss.
Scenario 2:
A victim has 500 USDC and grants infinite approval to the BelongCheckIn contract for convenience.
Venue_A requires a payment of 500 USDC.
The victim approves the BelongCheckIn for the required USDC amount and completes the payment to Venue_A.
At that moment the victim's balance is 0, so immediate replays would fail.
The victim later receives 10,000 USDC to their address for other uses.
Because payToVenue does not:
check the caller, and
enforce a nonce preventing replay, Venue_A can call
payToVenueagain for the previously-signed payment (500 USDC) and drain the newly deposited funds.
Venue exits with the user's funds causing user loss.
The Problematic code
The vulnerable code path allows this behavior because there is no nonce, deadline, nor caller restriction on execution:
Impact
A user’s USDC/LONG funds can be stolen. Venues are not controlled by the protocol and must be treated as untrusted actors. Even if venues are initially vetted, they could turn malicious later and exploit this replay behavior.
Mitigation
Two possible mitigations are proposed:
Add a nonce (and optionally a deadline) to the signed
CustomerInfopayload and store used nonces to prevent replays.Restrict execution of
payToVenueso that only the customer (or an authorized executor) can call it. Note: restricting only to the customer may reduce flexibility (e.g., paying from another address), so the nonce + deadline approach is recommended.
Link to Proof of Concept
https://gist.github.com/blackgrease/cb90d9d6706dfc83b27ed97507d87aaa
Proof of Concept
A runnable Foundry PoC is provided in the gist above. The PoC demonstrates Scenario 1.
Run with:
Test Console logs (from the PoC):
Explaining the test setup:
The PoC forks mainnet and uses on-chain Uniswap Router/Factory/Quoter addresses to create a USDC/LONG pool so venue deposits and payments function.
Deploys necessary contracts and creates the Uniswap Pool so the Venue Deposit and customer payment flows can be exercised.
Because the original LONG contract did not fit the flow in testing, a Mock LONG is used in the PoC (the issue demonstrated is unchanged).
Due to multiple interactions, a stack trace was not provided in the report; the PoC and test logs above show the exploit behavior.
Foundry Setup
Clone the repo:
Install Foundry dependencies:
Update remappings in foundry.toml (replace previous commented remappings with the following):
Was this helpful?