> For the complete documentation index, see [llms.txt](https://reports.immunefi.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://reports.immunefi.com/iop-paradex/46747-sc-insight-self-referral-vulnerability-in-account-referral-system.md).

# #46747 \[SC-Insight] Self-Referral Vulnerability in Account Referral System

**Submitted on Jun 4th 2025 at 07:21:29 UTC by @Catchme for** [**IOP | Paradex**](https://immunefi.com/audit-competition/iop-paradex)

* **Report ID:** #46747
* **Report Type:** Smart Contract
* **Report severity:** Insight
* **Target:** <https://github.com/tradeparadex/audit-competition-may-2025/tree/main/paraclear>
* **Impacts:**
  * Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

## Description

## Summary

There is a critical vulnerability in the `set_account_referral` function that allows an account to be set as its own referrer, creating a circular referral system that can be exploited to reduce trading fees unfairly.

## Vulnerability Details

In `AccountComponent::set_account_referral`:

```cairo
fn set_account_referral(
    ref self: ComponentState<TContractState>,
    account: ContractAddress,
    referrer: ContractAddress,
    commission: felt252,
    discount: felt252,
) {
    self.assert_only_role(roles::CONFIGURATOR_ROLE);
    self
        .Paraclear_account_referral
        .write(
            account,
            AccountReferral {
                referrer: referrer, fee_commission: commission, fee_discount: discount,
            },
        );
    self
        .emit(
            AccountReferralUpdate {
                account: account,
                referrer: referrer,
                fee_commission: commission,
                fee_discount: discount,
            },
        );
}
```

The function lacks validation to ensure that `account != referrer`. This allows setting up self-referrals where an account can refer itself, creating a circular referral relationship.

## Impact

1. **Fee Manipulation**: An account could receive both fee discounts as a referred account and fee commissions as a referrer for the same trades, allowing users to significantly reduce trading fees.
2. **Economic Exploit**: The system's fee calculation logic in `get_trade_fee_and_referral_commission` would apply both a discount and generate commissions for the same account:

   ```cairo
   if self.referral.fee_discount != @0 {
       let one_minus_discount = math::MULTIPLIER - (*self.referral.fee_discount).try_into().unwrap();
       let fee_after_discount = mul_128(fee, one_minus_discount);
       if self.referral.fee_commission != @0 {
           let fee_commission = mul_128(
               fee_after_discount, (*self.referral.fee_commission).try_into().unwrap(),
           );
           return (fee_after_discount, *self.referral.referrer, fee_commission);
       }
       return (fee_after_discount, *self.referral.referrer, 0);
   }
   ```
3. **Protocol Revenue Loss**: This could result in reduced protocol revenue from trading fees.

## Recommended Fix

Add a validation check to ensure that `account` and `referrer` cannot be the same address:

```cairo
fn set_account_referral(
    ref self: ComponentState<TContractState>,
    account: ContractAddress,
    referrer: ContractAddress,
    commission: felt252,
    discount: felt252,
) {
    self.assert_only_role(roles::CONFIGURATOR_ROLE);
    
    // Prevent self-referral
    assert(account != referrer, 'Self-referral not allowed');
    
    self
        .Paraclear_account_referral
        .write(
            account,
            AccountReferral {
                referrer: referrer, fee_commission: commission, fee_discount: discount,
            },
        );
    self
        .emit(
            AccountReferralUpdate {
                account: account,
                referrer: referrer,
                fee_commission: commission,
                fee_discount: discount,
            },
        );
}
```

## Proof of Concept

## Proof of Concept

1. A user with `CONFIGURATOR_ROLE` calls `set_account_referral` with:
   * `account` = user's address
   * `referrer` = same user's address
   * `commission` =3000
   * `discount` = 2000
2. When the user trades, they receive both a 20% discount on fees and earn 30% commission on these already discounted fees.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://reports.immunefi.com/iop-paradex/46747-sc-insight-self-referral-vulnerability-in-account-referral-system.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
