# Withdrawal

A withdrawal starts with dvUSDC and ends with net USDC.

The withdrawal path measures realised yield from the actual USDC received, not from estimates, then applies the protocol fee only when realised yield is positive.

```mermaid
sequenceDiagram
    participant W as Wallet
    participant R as VaultRouter
    participant A as Aave
    participant M as Morpho
    participant F as FeeCollector

    W->>R: withdraw(shares, wallet, minUsdcOut)
    R->>R: Compute principalOut
    R->>R: Reduce cost basis and burn dvUSDC
    R->>R: Plan Aave and Morpho capacity
    R->>A: Withdraw exact Aave slice if needed
    R->>M: Withdraw exact Morpho slice if needed
    R->>R: Measure actual USDC delta
    R->>R: Compute realised yield and fee
    R->>F: Collect fee if yield exists
    R->>W: Transfer net USDC
```

## Step-By-Step

1. The caller must be the wallet or an approved operator.
2. The wallet must have enough dvUSDC.
3. The router calculates the withdrawn principal as a proportional slice of the wallet's cost basis.
4. The router reduces the wallet's cost basis and burns dvUSDC before external vault calls.
5. The router snapshots its USDC balance before redemption.
6. The router plans withdrawal capacity across Aave and Morpho.
7. The router calculates the estimated gross USDC value of the burned shares.
8. The router assigns a proportional withdrawal target to Aave and Morpho.
9. If one venue cannot satisfy its target, the shortfall redirects to the other venue when possible.
10. If combined capacity cannot satisfy the withdrawal, the call reverts.
11. The router withdraws the planned amounts from Aave and Morpho.
12. The router measures the actual USDC received as a balance delta.
13. The router computes realised yield as `actualGross - principalOut`, floored at zero.
14. The fee collector receives 10% of realised yield if realised yield exists.
15. The wallet receives the remaining USDC, subject to `minUsdcOut`.

The deposit pause does not apply to withdrawals.

## Withdrawal Capacity Planning

The router uses the same capacity planning logic for the public `withdrawCapacity()` view and the state-changing `withdraw()` function.

**For Aave**, the router checks:

* the router's aToken balance;
* current USDC liquidity available in the aToken contract;
* whether the reserve is active and not paused.

**For Morpho**, the router checks:

* the router's Morpho shares valued through `convertToAssets`;
* `maxWithdraw(address(this))`;
* whether the Morpho view path is reachable within the bounded gas stipend.

If Morpho valuation fails and the router has Morpho exposure, `withdraw()` reverts with `MorphoUnreachable`. Integrators can call `withdrawCapacity()` first and inspect `morphoReachable` to avoid submitting a transaction that is expected to fail.

The redirect logic is intentionally one-step. After the router confirms total combined capacity is sufficient, at most one venue can be short relative to its proportional target. The shortfall can therefore be shifted to the other venue without a loop.

## Realised Yield Calculation

Fees are based on realised withdrawal results, not estimates.

The router measures:

```
actualGross = USDC balance after redemption - USDC balance before redemption
realisedYield = max(actualGross - principalOut, 0)
fee = ceil(realisedYield * 10%)
netToWallet = actualGross - fee
```

This design matters because vault calls can include rounding, liquidity effects, or exact-asset redemption behaviour. Divigent charges fees only after the router knows what actually arrived.

If `actualGross <= principalOut`, the realised yield is zero and the fee is zero.

For the full fee model, see [Fees](/divigent-docs/protocol/fees.md).

## Slippage Protection

The `minUsdcOut` parameter bounds the net USDC the wallet must receive. If the final transfer to the wallet would be less than `minUsdcOut`, the call reverts.

## Common Reverts

| Error                  | Cause                                                            |
| ---------------------- | ---------------------------------------------------------------- |
| `NotAuthorized`        | Caller is not the wallet or an approved operator.                |
| `InsufficientShares`   | Wallet does not hold enough dvUSDC.                              |
| `MorphoUnreachable`    | Morpho view path failed and router has Morpho exposure.          |
| `InsufficientCapacity` | Combined Aave and Morpho capacity cannot satisfy the withdrawal. |
| `SlippageExceeded`     | Net USDC received is below `minUsdcOut`.                         |


---

# Agent Instructions: 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:

```
GET https://divigent.gitbook.io/divigent-docs/protocol/withdrawal.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
