> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tplus.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Rebalancing

> How liquidity rebalancing fees and rewards are computed, with worked examples.

A Tplus asset is backed by a separate [vault](/funds/asset-parameters) on each chain it lives on. To keep liquidity spread across them, the protocol charges a fee or pays a reward — up to 2.5% — on deposits, withdrawals, and settlements, based on how the movement shifts a vault relative to its target.

Each vault has a minimum target weight (`minWeight`, a per-(asset, chain) [parameter](/funds/asset-parameters)). A vault below its target is underweight; at or above it, overweight.

| Movement                             | Effect                           | Charge |
| ------------------------------------ | -------------------------------- | ------ |
| Deposit into an underweight vault    | Moves it toward target           | Reward |
| Deposit into an overweight vault     | Pushes other vaults under target | Fee    |
| Withdrawal from an underweight vault | Moves it further below target    | Fee    |
| Withdrawal from an overweight vault  | —                                | None   |

A settlement is treated as both legs at once: the asset leaving a vault as a withdrawal, the asset entering a vault as a deposit. Rebalancing applies only to pooled assets (one [fungible asset](/funds/fungibility) spread across vaults); an isolated, single-vault balance has nothing to rebalance and is never charged.

## How the rate is computed

Each vault's **weight** is its share of the asset's total balance across all chains. Its **target** is derived from the configured weights, divided by a buffer so the per-vault minimums sum to less than 100% and can all be satisfied at once:

```text theme={null}
weight = vault_balance / sum(vault_balance)          # one asset, across its vaults
target = min_weight / (buffer * sum(min_weight))      # buffer = 1.2 (per-asset parameter)
```

A movement is scored per affected vault on its **average distance below target** across the move — the mean of its weight before and after, with the before-weight capped at target so only the portion below target is charged:

```text theme={null}
avg    = ( min(weight_before, target) + weight_after ) / 2
rate   = 2.5% * (target - avg) / target            # 0 when weight_after >= target
charge = amount * rate
```

`rate` runs from 0 (vault stays at or above target) to 2.5% (vault stranded at 0% weight). Applying it:

* **Deposit / settlement-in.** The receiving vault earns a reward if it is below target. Every *other* vault the inflow pushes below target is charged a fee — depositing raises the asset's total, lowering every other vault's weight. The user pays or receives the **net** of the two.
* **Withdrawal / settlement-out.** Only the source vault is scored, and only if it ends below target. Withdrawals never earn a reward.

## Worked examples

Three vaults, weights 30 / 10 / 10, buffer 1.2. Targets:

```text theme={null}
target_eth  = 30 / (1.2 * 50) = 50.00%
target_arb  = 10 / (1.2 * 50) = 16.67%
target_base = 10 / (1.2 * 50) = 16.67%
```

The targets sum to 83.3% (= 1 / 1.2), the buffer's headroom.

**Deposit that pays a fee.** Balances 500 / 200 / 300 (total 1000); deposit 100 into Base.

```text theme={null}
Ethereum:  500/1000 = 50.00%  ->  500/1100 = 45.45%   (drops below 50% target)
  avg  = (min(50.00%, 50%) + 45.45%) / 2 = 47.73%
  rate = 2.5% * (50% - 47.73%) / 50%     = 0.114%
  fee  = 100 * 0.114%                    = 0.114
Arbitrum:  20.00% -> 18.18%, both above 16.67% target  ->  no fee
Base (receiving): 30% > 16.67% target  ->  no reward
net: fee ~ 0.114
```

**Deposit that earns a reward.** Balances 100 / 400 / 500; deposit 400 into Ethereum (underweight at 10% vs 50%).

```text theme={null}
Ethereum:  100/1000 = 10.00%  ->  500/1400 = 35.71%
  avg    = (10.00% + min(35.71%, 50%)) / 2 = 22.86%
  rate   = 2.5% * (50% - 22.86%) / 50%     = 1.357%
  reward = 400 * 1.357%                     = 5.43
Arbitrum, Base above target  ->  no fee
net: reward ~ 5.43   (paid from the fee account, capped at its balance)
```

**Withdrawal that pays a partial fee.** Balances 550 / 200 / 250; withdraw 200 from Ethereum.

```text theme={null}
Ethereum:  550/1000 = 55.00%  ->  350/800 = 43.75%
  weight_before capped at target: min(55%, 50%) = 50%
  avg  = (50% + 43.75%) / 2 = 46.875%
  rate = 2.5% * (50% - 46.875%) / 50% = 0.156%
  fee  = 200 * 0.156%                 = 0.3125
```

Ethereum started above target, so only the slide below 50% is charged — not the whole 55% to 43.75% move. A vault stranded at 0% weight hits the 2.5% per-vault cap; a deposit charged across two such vaults costs up to 5%.

## Application and timing

* **Deposits** are charged when the balance is credited. **Withdrawals and settlements** are computed at request time — and counted in the solvency check — but applied only after the on-chain transaction confirms. A canceled withdrawal is charged nothing.
* Rewards are paid from a protocol fee account and capped at its balance; fees are collected to the same account.
* The rate uses the configured target weights at the moment of the movement, so it shifts as vault balances and pending outflows change.
