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

# Auto-Sweep

> Liquid Treasury auto-sweep configuration for an EVM Liquidity Provider

Auto-Sweep allows a Liquidity Provider (LP) to hold working capital in Liquid Treasury while `MultiliquidSwap` coordinates settlement conversions at execution time.

The feature has two complementary operations:

* **Prefund** runs before a user-requested stablecoin-output swap. It redeems the LP's Liquid Treasury token (`$TSY`) into the stablecoin required for settlement.
* **Sweep** runs after an eligible stablecoin-input swap. It deposits the stablecoin balance received by the LP vault during that swap into Liquid Treasury.

Both operations are internal LP-owned swap legs. The LP does not add them to the user's calldata or permit. The user authorizes a **user-requested leg**, and `MultiliquidSwap` derives any **LP prefund or sweep leg** from current execution state using the LP vault's separate permissions.

## How It Works

```mermaid theme={null}
sequenceDiagram
    actor User
    actor Operator as Execution Operator
    participant Swap as MultiliquidSwap
    participant LP as LP Vault
    participant Treasury as Treasury Delegate
    participant Requested as User-Route Delegate

    User-->>Operator: Authorize user-requested route
    Operator->>Swap: Submit user-requested leg
    opt User requested prefunded route 8–11
        Swap->>Treasury: Derive exact-out Liquid Treasury redemption
        Treasury->>LP: Supply required stablecoin inventory
    end
    Swap->>Requested: Execute user-requested leg
    opt Eligible user input and LP sweep allowance
        Swap->>LP: Measure received balance delta
        Swap->>Treasury: Deposit delta into Liquid Treasury
        Treasury->>LP: Return $TSY and Liquid Treasury credits
    end
    Swap-->>Operator: Emit one Swap event per executed leg
```

### Prefund

Prefund is explicit in the **user-requested route**. It is not a separate route submitted by the LP:

1. The user-facing integrator selects [route `8`, `9`, `10`, or `11`](/evm/guides/integration#route-model), and the execution operator submits it for the user.
2. `MultiliquidSwap` quotes that user-requested leg at execution time.
3. The contract derives an LP-owned stablecoin-to-stablecoin exact-out leg from Liquid Treasury into the stablecoin needed by the user-requested leg.
4. The LP vault is the user and receiver of the derived leg; `MultiliquidSwap` is its operator.
5. The derived LP prefund and user-requested leg settle atomically.

The contract skips a no-op prefund when Liquid Treasury already supplies the required inventory. Otherwise, a user-requested prefunded route requires sufficient `$TSY` balance, Liquid Treasury credits, token approval, protocol allowance, and Treasury Delegate settlement capacity.

### Sweep

Sweep is automatic on eligible user-requested routes once the LP vault has opted in for the user's input asset:

1. Before the user-requested leg, the contract reads the LP vault's input-stablecoin balance.
2. The user-requested leg settles into the LP vault.
3. The contract reads the balance again and uses only the positive delta as the sweep input.
4. A zero standing protocol allowance from the LP vault skips the sweep.
5. A positive allowance causes the contract to derive an LP-owned exact-in deposit into Liquid Treasury.

The sweep does not consume stablecoin inventory that was already in the LP vault before the user-requested leg. Its minimum `$TSY` output is quoted internally at execution time, and the derived LP leg settles atomically with the user-requested swap.

Liquid Treasury deposits create `$TSY` tokens and Treasury Delegate credits for the LP vault. The [Liquid Treasury application page](/applications/liquid-treasury#yield-bearing-integration-treasury-delegate) describes token and credit accounting.

## Route Behavior

This table starts with the route requested and authorized by the **user**. The last two columns show whether `MultiliquidSwap` can add a separate Liquid Treasury leg owned by the LP.

| User-requested route              |        IDs | Derived Liquid Treasury prefund | Derived Liquid Treasury sweep |
| --------------------------------- | ---------: | ------------------------------- | ----------------------------- |
| Stablecoin → RWA                  |   `0`, `1` | No                              | Eligible                      |
| RWA → stablecoin                  |   `2`, `3` | No                              | No                            |
| RWA → RWA                         |   `4`, `5` | No                              | No                            |
| Stablecoin → stablecoin           |   `6`, `7` | No                              | Eligible                      |
| Prefunded RWA → stablecoin        |   `8`, `9` | Yes                             | No                            |
| Prefunded stablecoin → stablecoin | `10`, `11` | Yes                             | Eligible                      |

“Eligible” does not mean the user controls the LP sweep. A sweep executes only when the LP has configured Liquid Treasury and the LP vault has granted a sufficient standing allowance for the user-requested input asset. Prefund may be skipped when the derived conversion would be an identity operation.

The contract reads Auto-Sweep configuration from the user-requested leg's `stablecoinDelegateID`. For stablecoin-to-stablecoin routes, the integrator's input-side or output-side delegate selection therefore determines which LP domain, configuration, and custody account apply. The LP provides integration partners with the stablecoin delegate ID that identifies the LP domain.

## Who Controls Each Part

Liquid Treasury Auto-Sweep is controlled at three levels:

| Control                     | Owner                         | Effect                                                                                       |
| --------------------------- | ----------------------------- | -------------------------------------------------------------------------------------------- |
| Liquid Treasury destination | The LP admin                  | Sets `TSY_YIELD` for the LP delegate; zero disables all automatic LP legs                    |
| Standing input allowance    | The LP vault                  | Enables derived spending from the LP vault for one input asset, such as USDC                 |
| User-requested route ID     | User-facing integrator + user | Routes `8`–`11` ask the contract to derive prefund; the user authorizes this route selection |

This separation supports several operating modes:

| Mode              | LP configuration                                                                            | Required user-facing integration behavior                                          |
| ----------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Disabled          | The configured destination is `bytes32(0)`                                                  | The integrator does not submit prefunded routes; they revert while disabled        |
| Sweep only        | Liquid Treasury is configured and only selected sweep inputs are authorized                 | The integrator submits base routes `0`–`7`; eligible user inputs can trigger sweep |
| Prefund only      | Liquid Treasury is configured, `$TSY` is authorized, and sweep-input allowances remain zero | The integrator selects prefunded routes `8`–`11` where LP inventory is needed      |
| Prefund and sweep | Liquid Treasury, `$TSY` prefund inventory, and selected sweep inputs are authorized         | The integrator selects prefunded routes where needed; base routes remain available |

Standing allowances can be bounded and replenished as they are spent, or set to `type(uint256).max`. A maximum allowance is treated as unlimited and is not decremented by successful swaps.

## LP Enablement Steps

This section assumes the LP stablecoin delegate is initialized, its custody address is configured, and it accepts Liquid Treasury.

The examples assume an initialized `ml` client from the [EVM Integration Guide](/evm/guides/integration). Narrative references use LP terminology; `ml.issuerAdmin` remains the exact SDK module name for the delegate's on-chain admin interface.

<Steps>
  <Step title="LP admin: Select Liquid Treasury">
    The LP admin sets `TSY_YIELD` as the `autoLiquidityStablecoinID` for the
    existing LP stablecoin delegate.
  </Step>

  <Step title="LP vault: Approve the Treasury Delegate">
    The LP vault approves the Treasury Delegate to pull USDC for Liquid Treasury
    sweeps. Approval for `$TSY` is required only when the LP also uses prefunded
    JIT redemption.
  </Step>

  <Step title="LP vault: Grant standing protocol allowances">
    The LP vault authorizes `MultiliquidSwap` to spend USDC for derived Liquid
    Treasury sweeps. A separate `$TSY` allowance enables optional prefund.
  </Step>

  <Step title="LP + operator: Verify enablement">
    The LP operations team confirms the configured Liquid Treasury ID and
    previews an eligible sweep. The execution operator simulates the final
    user-requested transaction.
  </Step>
</Steps>

### Configuration Values

```typescript theme={null}
import { mainnet } from "@uniformlabs/multiliquid-evm-sdk";

const lpStablecoinID = mainnet.assetIds.stablecoin.USDC;
const sweepInputStablecoinID = mainnet.assetIds.stablecoin.USDC;
const liquidTreasuryID = mainnet.assetIds.stablecoin.TSY_YIELD;

const [lpVault, sweepInputInfo, liquidTreasuryInfo, treasuryDelegate] =
  await Promise.all([
    ml.delegates.getStablecoinCustodyAddress(lpStablecoinID),
    ml.assets.getStablecoinInfo(sweepInputStablecoinID),
    ml.assets.getStablecoinInfo(liquidTreasuryID),
    ml.delegates.getDelegateAddress(liquidTreasuryID),
  ]);
```

The example uses USDC as the sweep input and Liquid Treasury as the destination. A separate LP stablecoin registration can replace `lpStablecoinID` when the LP domain is not the Uniform Labs USDC registration.

### 1. LP Admin: Select Liquid Treasury

The LP admin sets Liquid Treasury as the destination for the existing LP stablecoin delegate:

```typescript theme={null}
await ml.issuerAdmin.setAutoLiquidityStablecoinID({
  stablecoinID: lpStablecoinID,
  autoLiquidityStablecoinID: liquidTreasuryID,
});
```

The delegate forwards the setting to `MultiliquidSwap`. The transaction emits `AutoLiquidityStablecoinIDSet`.

The setting applies only to user-requested routes whose `stablecoinDelegateID` selects this LP domain.

### 2. LP Vault: Approve the Treasury Delegate

ERC-20 approval authorizes the Treasury Delegate to pull tokens from the LP vault during settlement. The wallet client below must sign as the LP vault.

USDC approval enables the Liquid Treasury sweep:

```typescript theme={null}
import { maxUint256 } from "viem";
import { erc20Abi } from "@uniformlabs/multiliquid-evm-sdk";

await lpVaultWalletClient.writeContract({
  account: lpVaultWalletClient.account,
  address: sweepInputInfo.assetAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [treasuryDelegate, maxUint256],
  chain: lpVaultWalletClient.chain,
});
```

An LP that also uses prefunded JIT redemption grants a separate `$TSY` approval:

```typescript theme={null}
await lpVaultWalletClient.writeContract({
  account: lpVaultWalletClient.account,
  address: liquidTreasuryInfo.assetAddress,
  abi: erc20Abi,
  functionName: "approve",
  args: [treasuryDelegate, maxUint256],
  chain: lpVaultWalletClient.chain,
});
```

The Liquid Treasury administrator separately maintains the Treasury Delegate custody approvals and settlement inventory assumed by this guide.

### 3. LP Vault: Grant Standing Protocol Allowances

`swapInputAllowance` is separate from ERC-20 approval. It authorizes `MultiliquidSwap` to insert and operate a derived LP leg.

The LP creates an SDK client whose wallet signs as the LP vault:

```typescript theme={null}
import { createMultiliquidClient } from "@uniformlabs/multiliquid-evm-sdk";

const mlAsLpVault = createMultiliquidClient({
  deployment: ml.deployment,
  publicClient,
  walletClient: lpVaultWalletClient,
});
```

The helper below moves the current standing allowance to a chosen target:

```typescript theme={null}
import { maxUint256, type Hex } from "viem";

const swapOperator = mlAsLpVault.deployment.addresses.multiliquidSwap;

async function setAutoLegAllowance(assetInID: Hex, target: bigint) {
  const current = await mlAsLpVault.swap.getSwapInputAllowance(
    lpVault,
    swapOperator,
    assetInID,
  );

  if (current === target) return;

  await mlAsLpVault.swap.adjustSwapInputAllowance({
    operator: swapOperator,
    assetInID,
    amount: target > current ? target - current : current - target,
    increase: target > current,
  });
}

// Required for USDC sweep into Liquid Treasury.
await setAutoLegAllowance(sweepInputStablecoinID, maxUint256);

// Optional: required only for prefunded JIT redemption from $TSY.
await setAutoLegAllowance(liquidTreasuryID, maxUint256);
```

For the USDC allowance:

* `0` leaves Liquid Treasury sweep disabled for USDC; the user-requested leg can continue without the sweep.
* A sufficient positive allowance enables USDC sweep into Liquid Treasury.
* A positive but insufficient allowance causes the complete user transaction to revert atomically.

`type(uint256).max` is treated as unlimited and is not decremented by successful swaps. A bounded allowance is decremented as it is spent and must include enough headroom for execution-time amounts.

### 4. LP + Operator: Verify Enablement

The LP operations team first confirms that the LP domain points to Liquid Treasury:

```typescript theme={null}
const configuredDestination =
  await ml.swap.getAutoLiquidityStablecoinID(lpStablecoinID);

if (configuredDestination !== liquidTreasuryID) {
  throw new Error("Liquid Treasury is not configured for this LP domain");
}
```

The LP operations team can then preview an eligible USDC-input route:

```typescript theme={null}
import { ROUTE_IDS } from "@uniformlabs/multiliquid-evm-sdk";

const userRequestedInput = {
  routeId: ROUTE_IDS.STABLE_TO_RWA_EXACT_IN,
  assetInID: sweepInputStablecoinID,
  assetOutID: rwaID,
  stablecoinDelegateID: lpStablecoinID,
  assetInAmt: exactInput,
  assetOutAmt: minimumOutput,
};

const preview = await ml.swap.getAutoLiquidityPreview({
  user: userAddress,
  input: userRequestedInput,
});

console.log("LP vault:", preview.lpVault);
console.log("Liquid Treasury sweep:", preview.sweep);
```

The preview reports USDC sweep eligibility, the estimated input amount, the LP vault balance, and the standing protocol allowance. The final sweep amount remains unknown until execution because `MultiliquidSwap` measures the LP vault balance delta around the user-requested leg.

The execution operator should simulate the final bounded transaction with the actual user, operator, receiver, and permit:

```typescript theme={null}
const quote = await ml.quote.quoteSwap({
  user: userAddress,
  input: userRequestedInput,
  simulate: true,
  operator: operatorAddress,
  receiver: receiverAddress,
  permit,
});

console.log("Settlement simulation:", quote.simulation);
```

Simulation exercises current user funds, LP balances, ERC-20 approvals, standing allowances, prices, whitelists, and delegate settlement state.

## Change or Disable Auto-Sweep

### Disable One Sweep Input

The LP vault sets that input asset's standing protocol allowance to zero using the `setAutoLegAllowance` helper. This disables Liquid Treasury sweep for that asset without affecting other sweep inputs or user-requested swaps.

Revoking the protocol allowance does not revoke the token's ERC-20 approval. The LP vault revokes both controls if the Treasury Delegate should no longer be able to pull that asset from custody.

### Stop Using Prefund but Keep Sweep

The LP cannot rewrite the user's route during execution. The LP coordinates with user-facing integrators to use base route IDs `2`, `3`, `6`, or `7` instead of prefunded routes `8`–`11`. This stops Liquid Treasury prefund requests while leaving Liquid Treasury sweep available on otherwise eligible stablecoin-input routes.

### Disable All Automatic Legs

```typescript theme={null}
import { zeroHash } from "viem";

await ml.issuerAdmin.setAutoLiquidityStablecoinID({
  stablecoinID: lpStablecoinID,
  autoLiquidityStablecoinID: zeroHash,
});
```

Setting zero disables Liquid Treasury prefund and sweep for the LP delegate. The LP admin should notify integration partners before disabling it: a user-requested prefunded route does not fall back to its base route and will revert while Auto-Sweep is disabled. Existing protocol allowances and ERC-20 approvals remain stored, so the LP vault removes them separately when retiring the configuration.

### Re-Enable Liquid Treasury

The LP admin can restore `liquidTreasuryID` after confirming the Treasury Delegate whitelist, per-asset terms, custody inventory, token approvals, and protocol allowances. The restored configuration applies immediately to subsequent user-requested swaps that select the LP delegate.

## Monitoring

For LP reconciliation, every user-requested and derived LP leg emits its own unified `Swap` event:

* Derived Liquid Treasury prefund events use stablecoin-to-stablecoin exact-out route `7`.
* Derived Liquid Treasury sweep events use stablecoin-to-stablecoin exact-in route `6`.
* For derived LP events, the event's user and receiver are the LP vault, and its operator is `MultiliquidSwap`.
* For the user-requested event, the user, receiver, operator, and requested route remain the user transaction's values.

The REST API counts automatic Liquid Treasury prefund and sweep legs as realized swap legs in transaction history and volume analytics. The LP reporting pipeline should distinguish the user-requested leg from internal Liquid Treasury legs using the route together with the user, receiver, and operator; route `6` or `7` alone is not sufficient because users can also request those routes directly.

<CardGroup cols={2}>
  <Card title="Liquid Treasury" icon="landmark" href="/applications/liquid-treasury">
    Liquid Treasury token, credit, and yield mechanics
  </Card>

  <Card title="MultiliquidSwap" icon="code" href="/evm/contracts/multiliquid-swap">
    Automatic-leg execution mechanics
  </Card>
</CardGroup>
