# Referral fees

> Charge your own fee on the swaps your app sends to Intear DEX: referral_fees on swap_simple, execute_operations and deposits, who gets paid, and in what.

This page is part of the Intear DEX docs. Intear DEX is the `dex.intear.near` contract. https://docs.intear.tech/intear-dex/llms-full.txt has all of its pages in one file, and https://docs.intear.tech/llms.txt lists every page of the Intear docs.

An app can charge its own fee on the swaps it sends, with `referral_fees`: the accounts to pay and the fee each one gets, out of the swap's input. The engine takes the fees before the DEX gets the input, so they work the same on every DEX, and puts them in the inner balances of the accounts. Nothing is set up in advance other than registering the input asset, so each swap can charge different fees.

```json
"referral_fees": [["myapp.near", 5000], ["partner.near", 1000]]
```

Each fee is a `u32` out of 1000000, so `5000` is 0.5% and `1000` is 0.1%.

- At most 5 accounts, with fees that add up to at most 5% (`50000`). A fee of 0 charges nothing.
- The fees are in the swap's input asset, and go to the accounts' [inner balances](https://docs.intear.tech/intear-dex/guides/inner-balances.md), to [withdraw](https://docs.intear.tech/intear-dex/guides/inner-balances.md#withdraw) like any other asset.
- An account is only paid if the input asset is registered for it. Otherwise its fee isn't charged, and the trader keeps it. Anyone can [register the asset for it](https://docs.intear.tech/intear-dex/guides/inner-balances.md#register-assets) with `for`.
- With `ExactIn`, the fees come out of the amount, each rounded down, and the DEX swaps the rest. With `ExactOut`, they're added on top of what the DEX takes, rounded up, so that each fee is its fraction of the whole input.
- `swap_simple` returns the whole input, fees included, and the `constraint` of an `ExactOut` swap limits the whole input too. The trader's inner balance needs all of it.
- In [`execute_operations`](https://docs.intear.tech/intear-dex/guides/operations.md#execute_operations) and [deposits](https://docs.intear.tech/intear-dex/guides/operations.md#operations-in-a-deposit), only the first swap pays them.
- The DEX's own fees, and a fee discount it gives, apply to what the DEX gets, not to the referral fees.
- `referrer` is separate: it names your app in the events and to the DEX, but doesn't charge anything.

The [DEX Aggregator](https://docs.intear.tech/dex-aggregator/guides/referral-fees.md) puts the `fees` of its requests in `referral_fees` for Plach routes, and registers the input asset for the accounts that don't have it.

## Charge a fee

The [near CLI](https://docs.intear.tech/intear-dex/quickstart.md#before-you-start) examples below charge a 1% fee for bob.near on alice.near's swap of 1 NEAR to USDt, after a [storage deposit](https://docs.intear.tech/intear-dex/guides/storage.md#accounts), registering NEAR and USDt, and depositing 1 NEAR. Together they're [one script](#the-whole-script).

bob.near is paid in NEAR, the swap's input, so NEAR has to be registered for it first. It can do that itself, or anyone can do it for it:

```sh
# bob.near is paid in the swap's input, NEAR, so NEAR has to be registered for
# it. Anyone can register it, here alice.near, from its own storage balance.
near contract call-function as-transaction dex.intear.near register_assets \
  json-args '{"asset_ids": ["near"], "for": {"Account": "bob.near"}}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/referral-fees.sh

`simulate_swap_simple` takes the same `referral_fees`, and gives the same amounts as the swap would:

```sh
# The DEX swaps 0.99 NEAR, so simulate with the same referral fees
AMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \
  json-args '{
    "dex_id": "slimedragon.near/xyk",
    "message": "AQAAAEBCDwABAAAA3QAAAAA=",
    "trader": "alice.near",
    "asset_in": "near",
    "asset_out": "nep141:usdt.tether-token.near",
    "amount": {"ExactIn": "1000000000000000000000000"},
    "referral_fees": [["bob.near", 10000]]
  }' \
  network-config mainnet now | jq -r '.[1]')
MIN_AMOUNT_OUT=$((AMOUNT_OUT * 99 / 100))
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/referral-fees.sh

```sh
near contract call-function as-transaction dex.intear.near swap_simple \
  json-args "$(jq -n --arg min_amount_out "$MIN_AMOUNT_OUT" '{
    "dex_id": "slimedragon.near/xyk",
    "message": "AQAAAEBCDwABAAAA3QAAAAA=",
    "asset_in": "near",
    "asset_out": "nep141:usdt.tether-token.near",
    "amount": {"ExactIn": "1000000000000000000000000"},
    "referral_fees": [["bob.near", 10000]],
    "constraint": $min_amount_out
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```

The whole file, tested in CI: https://docs.intear.tech/snippets/cli/referral-fees.sh

The DEX swaps 0.99 NEAR, and 0.01 NEAR goes to bob.near's inner balance. The [`swap`](https://docs.intear.tech/intear-dex/reference/events.md#swap) event lists the fees each account got in `referral_fees_paid`, and its `amount_in` is what the DEX got, without them.

## In operations and deposits

`execute_operations` takes `referral_fees` next to `operations` and `referrer`:

```json
{
  "operations": [{ "SwapSimple": { ... } }, { "Withdraw": { ... } }],
  "referrer": "myapp.near",
  "referral_fees": [["myapp.near", 5000]]
}
```

A [deposit message](https://docs.intear.tech/intear-dex/reference/types.md#depositmessage) takes them in its object form, the same way, except that `referral_fees` can't be `null` there: leave it out instead. In both, only the first swap pays them: in a chain of swaps, the fee is in the first swap's input.

## The whole script

```sh
#!/usr/bin/env bash
# Swaps 1 NEAR from the inner balance for USDt, paying bob.near a referral fee
# of 1%. alice.near has never used Intear DEX, and neither has bob.near.
set -euo pipefail

near contract call-function as-transaction dex.intear.near storage_deposit \
  json-args '{}' \
  prepaid-gas '30.0 Tgas' attached-deposit '0.01 NEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction dex.intear.near register_assets \
  json-args '{"asset_ids": ["near", "nep141:usdt.tether-token.near"]}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

near contract call-function as-transaction dex.intear.near deposit_near \
  json-args '{}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1 NEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

# bob.near is paid in the swap's input, NEAR, so NEAR has to be registered for
# it. Anyone can register it, here alice.near, from its own storage balance.
near contract call-function as-transaction dex.intear.near register_assets \
  json-args '{"asset_ids": ["near"], "for": {"Account": "bob.near"}}' \
  prepaid-gas '30.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send

# The DEX swaps 0.99 NEAR, so simulate with the same referral fees
AMOUNT_OUT=$(near contract call-function as-read-only dex.intear.near simulate_swap_simple \
  json-args '{
    "dex_id": "slimedragon.near/xyk",
    "message": "AQAAAEBCDwABAAAA3QAAAAA=",
    "trader": "alice.near",
    "asset_in": "near",
    "asset_out": "nep141:usdt.tether-token.near",
    "amount": {"ExactIn": "1000000000000000000000000"},
    "referral_fees": [["bob.near", 10000]]
  }' \
  network-config mainnet now | jq -r '.[1]')
MIN_AMOUNT_OUT=$((AMOUNT_OUT * 99 / 100))

near contract call-function as-transaction dex.intear.near swap_simple \
  json-args "$(jq -n --arg min_amount_out "$MIN_AMOUNT_OUT" '{
    "dex_id": "slimedragon.near/xyk",
    "message": "AQAAAEBCDwABAAAA3QAAAAA=",
    "asset_in": "near",
    "asset_out": "nep141:usdt.tether-token.near",
    "amount": {"ExactIn": "1000000000000000000000000"},
    "referral_fees": [["bob.near", 10000]],
    "constraint": $min_amount_out
  }')" \
  prepaid-gas '100.0 Tgas' attached-deposit '1 yoctoNEAR' \
  sign-as alice.near network-config mainnet sign-with-keychain send
```
