57691 sc medium malicious referrer can permanently block eth payment flow

Submitted on Oct 28th 2025 at 08:24:15 UTC by @blackgrease for Audit Comp | Belongarrow-up-right

  • Report ID: #57691

  • Report Type: Smart Contract

  • Report severity: Medium

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

  • Impacts:

    • Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Affected Files: AccessToken.sol, Factory.sol and ReferralSystemV2.sol

The AccessToken allows users to pay for NFT mints using ETH either through mintStaticPrice or mintDynamicPrice. When mints are made using ETH, the mentioned functions call the internal function, AccessToken::_pay which will send payments to:

  1. the platform,

  2. referrer and

  3. creator

using a low-level call in SafeTransferLib::safeTransferETH. The low level correctly checks the success status of the call and reverts the transaction if the payment to any of the 3 addresses fails.

When deploying an AccessToken the protocol allows deployments to include a referral code. Anyone can create a referral code by calling Factory::createReferralCode as the code is a hash that includes their address. The code is linked to an address that will receive a small percentage when mint payments are made.

This code is included in the Factory::produce function arguments as referralCode. It is important to note, this code is not part of the data signed by the Signer address.

The AccessToken uses a "push-payment" flow. As a result of "pushing payments", a malicious referrer has the ability to permanently brick the ETH payment flow in AccessToken for all users by reverting. This renders the AccessToken contract permanently unable to receive mint payments via ETH and either have to:

  • resort to only payments using ERC20 tokens (the referrer will still get payments)

  • or, as an extreme measure, redeploy the AccessToken using a non-malicious referrer code; though this will require a name and symbol change.

This vector may also be triggered accidentally by a referrer creating a code from a contract that cannot receive ETH payments. Furthermore, once set, the code cannot be changed.

1

Consider this scenario

  • Malicious User creates referral code from address that does not accept ETH payments.

  • Victim uses this code in deploying AccessToken.

  • Any user transaction to mint an Access Token using ETH as the payment reverts at the referrer's payment.

  • The AccessToken ETH payment path is permanently unavailable.

The Associated Code

Below is the logic for the functions that make this issue possible:

The referral code creation - ReferralSystemV2::createReferralCode - inherited by Factory

The internal AccessToken::_pay function

The SafeTransferLib ETH payment logic

Impact

The impact of this issue is griefing due to the ETH flow becoming permanently blocked. The block is permanent because once set, the referral code cannot be changed. The owner/creator will be limited to only mint payments via ERC20 tokens. In this case, the malicious referrer will still receive the payments.

This also damages the potential profits for the owner/creator as it removes the flexibility of using native payments which limits how users can pay — depending on demand.

Furthermore, the contract logic promises an ETH payment flow but by this flow becoming unavailable, this promise is unfulfilled.

Mitigation

The recommended mitigation for this issue is to redesign payments to the referrer. The platformAddress can be considered safe as it is protocol owned. The creator address can also be seen as safe due to it making no sense to exploit this.

However, for the referrer payment, this should be a pull payment, where the referrer has to call the contract to claim their ETH payments. This fix will effectively prevent bricking the ETH payment flow.

https://gist.github.com/blackgrease/36d6ac771dcdcf6ee617491fdb559023

Proof of Concept

As proof of this issue, I have created a runnable Foundry PoC — "https://gist.github.com/blackgrease/36d6ac771dcdcf6ee617491fdb559023" — that outlines the above scenario (in Description).

Run with:

Additionally, in case of any issues running the PoC, the gist has a .txt Foundry Stack trace from the test - "PoC_StackTrace-testMaliciousReferrerBlocksETHPaymentFlow.txt" - which shows the revert on the referrer's payment.

1

Foundry Setup — Step 1: Clone the repo

Clone the Github repo:

2

Foundry Setup — Step 2: Install Foundry dependencies

  1. Install OpenZeppelin upgradeable contracts (no commit):

  1. Install OpenZeppelin contracts (no commit):

  1. Install solady via npm:

3

Foundry Setup — Step 3: Update Mappings in foundry.toml

Comment out the previous remappings block if present and replace with the new remappings.

Previous (example, commented out):

New remappings to add:

Was this helpful?