> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt
> Use this file to discover all available pages before exploring further.

# Basket Weights & Unit Calculations

> Understanding weight ranges, basket units, and how token ratios are calculated during rebalancing

## Overview

Basket weights define how tokens are proportioned within a Folio. During rebalancing, weight ranges allow the `AUCTION_LAUNCHER` to progressively adjust token ratios within bounds set by governance.

## Basket Unit (BU)

A Basket Unit (BU) is a theoretical unit of account representing a standardized bundle of the underlying tokens:

```solidity theme={null}
// D18{BU/share}
struct RebalanceLimits {
    uint256 low;   // (0, 1e27] Buy assets up to this limit
    uint256 spot;  // (0, 1e27] Point estimate for unrestricted calls
    uint256 high;  // (0, 1e27] Sell assets down to this limit
}
```

**Typical usage**: BUs are defined 1:1 with shares (`1e18`), but the protocol supports ranges up to `1e27`.

### Calculating Total Baskets

For a Folio with total supply of shares:

```solidity theme={null}
// {BU} = {share} * D18{BU/share} / D18
uint256 totalBaskets = (totalSupply * basketLimit) / 1e18;
```

## Weight Ranges

```solidity theme={null}
// D27{tok/BU}
struct WeightRange {
    uint256 low;   // [0, 1e54] Minimum weight (buy target)
    uint256 spot;  // [0, 1e54] Point estimate
    uint256 high;  // [0, 1e54] Maximum weight (sell target)
}
```

Weights define how many token quanta comprise one basket unit.

### Example: 60/40 Portfolio

```solidity theme={null}
// Target: 60% WETH / 40% USDC by value
// Assume: WETH = $3000, USDC = $1
// Portfolio value: $100,000

// WETH: $60,000 / $3000 = 20 WETH
// USDC: $40,000 / $1 = 40,000 USDC

// Per BU (assume 100 shares outstanding, 1 BU/share):
WeightRange memory wethWeight = WeightRange({
    low:  0.19e27,  // 0.19 WETH/BU
    spot: 0.20e27,  // 0.20 WETH/BU
    high: 0.21e27   // 0.21 WETH/BU
});

WeightRange memory usdcWeight = WeightRange({
    low:  38000e27,  // 38,000 USDC/BU (remember: 6 decimals)
    spot: 40000e27,  // 40,000 USDC/BU
    high: 42000e27   // 42,000 USDC/BU
});
```

## Weight Control

The `weightControl` flag in `RebalanceControl` determines whether the `AUCTION_LAUNCHER` can adjust weights:

```solidity theme={null}
struct RebalanceControl {
    bool weightControl;           // If AUCTION_LAUNCHER can move weights
    PriceControl priceControl;   // Price control mode
}
```

### Without Weight Control

* `AUCTION_LAUNCHER` must use the exact spot weights from `REBALANCE_MANAGER`
* All auction weight ranges collapse to the spot value
* Suitable for Folios with fixed monthly/quarterly targets

### With Weight Control

* `AUCTION_LAUNCHER` can progressively narrow weight ranges
* Cannot expand beyond initial `low` and `high` bounds
* Suitable for Folios maintaining specific percentage breakdowns over time

## Surplus and Deficit Calculations

During auctions, tokens are classified as **surplus** or **deficit** based on current balances vs. target ranges:

### Surplus

A token is in surplus when the Folio holds more than needed at the `high` limit:

```solidity theme={null}
// {tok}
uint256 targetBalance = (totalSupply * high_BU_limit * weight.high) / (1e18 * 1e27);

if (currentBalance > targetBalance) {
    uint256 surplus = currentBalance - targetBalance;
    // Can sell surplus in auctions
}
```

### Deficit

A token is in deficit when the Folio holds less than needed at the `low` limit:

```solidity theme={null}
// {tok}
uint256 targetBalance = (totalSupply * low_BU_limit * weight.low) / (1e18 * 1e27);

if (currentBalance < targetBalance) {
    uint256 deficit = targetBalance - currentBalance;
    // Must buy deficit in auctions
}
```

### Auction Pair Eligibility

A token pair is eligible for auction only if:

1. Sell token is in **surplus** (using `high` limit)
2. Buy token is in **deficit** (using `low` limit)

## Lot Sizing

Auction sell amounts are calculated as the minimum of:

1. **Surplus constraint**: How much sell token is surplus
2. **Deficit constraint**: How much buy token is needed (converted via price)
3. **Max auction size**: Governance-set maximum per token

```solidity theme={null}
function _getBid(...) internal view returns (uint256 sellAmount, ...) {
    // Calculate sell token surplus
    uint256 sellSurplus = sellBalance - 
        (totalSupply * limits.high * sellWeight.high) / (1e18 * 1e27);
    
    // Calculate buy token deficit
    uint256 buyDeficit = 
        (totalSupply * limits.low * buyWeight.low) / (1e18 * 1e27) - buyBalance;
    
    // Convert buy deficit to sell terms
    uint256 sellForDeficit = (buyDeficit * sellPrice) / buyPrice;
    
    // Take minimum, capped by maxAuctionSize
    sellAmount = Math.min(
        Math.min(sellSurplus, sellForDeficit),
        maxAuctionSize
    );
}
```

## Progressive Rebalancing

The `AUCTION_LAUNCHER` can run multiple auctions, progressively tightening both limits and weights:

```solidity theme={null}
// Auction 1: Wide ranges
WeightRange memory weth1 = WeightRange(0.19e27, 0.20e27, 0.21e27);
RebalanceLimits memory limits1 = RebalanceLimits(0.95e18, 1.0e18, 1.05e18);

// Auction 2: Narrower ranges (within original bounds)
WeightRange memory weth2 = WeightRange(0.195e27, 0.20e27, 0.205e27);
RebalanceLimits memory limits2 = RebalanceLimits(0.98e18, 1.0e18, 1.02e18);

// Auction 3: Collapsed to spot (rebalance complete)
WeightRange memory weth3 = WeightRange(0.20e27, 0.20e27, 0.20e27);
RebalanceLimits memory limits3 = RebalanceLimits(1.0e18, 1.0e18, 1.0e18);
```

<Warning>
  Weights can only be narrowed, never expanded. Attempting to widen ranges beyond the initial `low`/`high` values will revert.
</Warning>

## Dynamic vs Static Rebalancing

### Static Targets (weightControl = false)

Use when:

* Rebalancing to a specific token composition (e.g., "own 1000 WETH and 1M USDC")
* Target composition is known ahead of time
* Rebalances are infrequent (monthly, quarterly)

```solidity theme={null}
RebalanceControl memory control = RebalanceControl({
    weightControl: false,
    priceControl: PriceControl.NONE
});
```

### Dynamic Targets (weightControl = true)

Use when:

* Maintaining a percentage-based portfolio (e.g., "always 60/40 WETH/USDC")
* Token ratios must adapt as prices change
* Rebalances are frequent or continuous

```solidity theme={null}
RebalanceControl memory control = RebalanceControl({
    weightControl: true,
    priceControl: PriceControl.PARTIAL  // Often paired
});
```

## Units and Precision

### Weight Units

* **Format**: `D27{tok/BU}` (27 decimal fixed point)
* **Range**: `[0, 1e54]`
* **Calculation**: `1e27 = 1 token quantum per BU`

### Example with Different Decimals

```solidity theme={null}
// WETH (18 decimals): 0.5 WETH per BU
uint256 wethWeight = 0.5e27;  // 0.5 * 1e27

// USDC (6 decimals): 1500 USDC per BU
uint256 usdcWeight = 1500e27; // 1500 * 1e27

// Target balance for 100e18 shares at 1e18 BU/share:
// WETH: (100e18 * 1e18 * 0.5e27) / (1e18 * 1e27) = 50e18 WETH
// USDC: (100e18 * 1e18 * 1500e27) / (1e18 * 1e27) = 150000e6 USDC
```

## Handling Zero Weights

Zero weights are used to remove tokens from the basket:

```solidity theme={null}
// Remove USDT from basket
WeightRange memory usdtWeight = WeightRange({
    low:  0,  // Sell down to zero
    spot: 0,
    high: 0
});

// After rebalancing completes:
// - USDT balance will be zero
// - Can call removeFromBasket() permissionlessly
```

## Common Patterns

### Equal-Weighted Portfolio

```solidity theme={null}
// 3 tokens, equal weight by value
// Assume all tokens = $1 each for simplicity

WeightRange memory weight = WeightRange({
    low:  0.32e27,  // Allow some flexibility
    spot: 0.333333e27,
    high: 0.35e27
});

// Apply same weight to all 3 tokens
```

### Capped Exposure

```solidity theme={null}
// Want 70% WETH, but cap at 1000 WETH total

WeightRange memory wethWeight = WeightRange({
    low:  6.5e18,   // 65% of target (per BU)
    spot: 7.0e18,   // 70% target
    high: 7.5e18    // 75% max
});

uint256 maxAuctionSize = 1000e18;  // Hard cap at 1000 WETH
```

## Validation Rules

```solidity theme={null}
// Weights must be ordered: low ≤ spot ≤ high
require(
    weight.low <= weight.spot && weight.spot <= weight.high,
    "Invalid weight range"
);

// All weights are valid: [0, 1e54]
require(weight.low >= 0 && weight.high <= 1e54, "Weight out of bounds");

// When narrowing, must stay within original bounds
require(
    newWeight.low >= originalWeight.low &&
    newWeight.high <= originalWeight.high,
    "Cannot expand weight range"
);
```

## Gas Optimization

Weight calculations happen on every `getBid()` call. To optimize:

1. Use collapsed ranges (`low == spot == high`) for final auctions
2. Limit the number of tokens in rebalance (affects calculation loops)
3. Consider `maxAuctionSize` caps to prevent excessive lot sizing calculations

## Related

* [Price Control Modes](/advanced/price-control)
* [Rebalancing Guide](/concepts/rebalancing)
* [Units Reference](/resources/units)
