57874 sc insight global metadata wipe on burn one promoter s payout clears the shared erc1155 token uri for all promoters of the same venue

Submitted on Oct 29th 2025 at 10:38:04 UTC by @xKeywordx for Audit Comp | Belongarrow-up-right

  • Report ID: #57874

  • Report Type: Smart Contract

  • Report severity: Insight

  • Target: https://github.com/immunefi-team/audit-comp-belong/blob/main/contracts/v2/tokens/base/ERC1155Base.sol

  • Impacts: Unintended alteration of what the NFT represents (e.g. token URI, payload, artistic content)

Description

promoterToken is an ERC1155 where the tokenId is derived from the venue's venueId (venueId = Helper.getVenueId(venue)), and all promoters of the same venue receive balances on that same tokenId.

According to the protocol's docs:

  • https://belongnet.github.io/docs/belong-checkin/promoter-earnings-guide

  • https://belongnet.github.io/docs/belong-checkin/token-value-creation

  • https://belongnet.github.io/docs/belong-checkin/venue-partner

a venue can and should be promoted by multiple promoters simultaneously. For a given venue (Event A), all promoters (KOLs) share the same promoterToken tokenId. Balances differ per promoter, but the tokenId is shared.

This is problematic because ERC1155Base::burn clears the token URI:

function burn(address from, uint256 tokenId, uint256 amount) public onlyRole(BURNER_ROLE) {
    _setTokenUri(tokenId, "");      // <— @audit clears the URI for this tokenId
    _burn(from, tokenId, amount);
}

burn is called inside BelongCheckIn::distributePromoterPayments():

Therefore, when any single promoter claims and burns part of their balance, the URI for that shared venueId is cleared for everyone, including other promoters who still hold balances for that venue.

Root cause

  • Shared tokenId across promoters: multiple promoters are minted balances of the same tokenId.

  • Global state in URI storage: token metadata is stored once per tokenId in mapping(uint256 => string) _tokenUri.

  • URI clearing on burn: ERC1155Base.burn calls _setTokenUri(tokenId, "") regardless of remaining supply or other holders.

Because ERC1155 URIs are global to an id, clearing it inside burn mutates what that id represents for all holders, not just the caller.

Impact

According to the Audit Competition rules (https://immunefi.com/audit-competition/audit-comp-belong/scope/#top) this falls under "Critical - Unintended alteration of what the NFT represents (e.g. token URI, payload, artistic content)".

  • Loss of metadata for all remaining holders of promoterToken for that venueId after any single payout.

  • UI/analytics issues: dashboards, wallets, and indexers relying on uri(tokenId) lose the venue’s descriptive data (image, name, attributes) for all promoters still holding balances.

  • Griefing attack vector: a promoter can trigger a minimal burn via a small claim and wipe the shared metadata for everyone else.

  • Metadata inconsistency: new mints will set the URI again, while burns will delete it, toggling on/off.

Revisit the metadata creation/deletion logic for ERC1155 tokens. Possible approaches (do not add new assumptions beyond the original content):

  • Avoid clearing the token URI on burn. Only clear metadata when total supply for tokenId reaches zero (if that is desired).

  • Store per-holder metadata if different promoters must have separate URIs (i.e., avoid sharing a single global URI when semantics require per-promoter metadata).

  • Use a reference-counting or supply-aware mechanism before mutating global token metadata.

Proof of Concept

chevron-rightTest POC: burning promoterToken for one promoter clears shared token URI for all promotershashtag

Add this test to belong-check-in.test.ts:

Test output:

Was this helpful?