> For the complete documentation index, see [llms.txt](https://docs.tropicalwater.xyz/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.tropicalwater.xyz/operational/user-flows.md).

# User Flows

### Deposit

```mermaid
sequenceDiagram
    actor User
    participant USDC as USDC Token
    participant Vault as OpportunityOVault

    User->>USDC: approve(vault, amount)
    User->>Vault: deposit(amount, receiver)
    Vault->>Vault: _updateRateFactor()
    alt cap != 0
        Vault->>Vault: check totalAssets() + amount ≤ cap
    end
    Vault->>USDC: transferFrom(user → vault, amount)
    Vault->>Vault: shares = amount × decimalOffset × RAY / cumulativeRateFactor
    Vault->>Vault: _mint(receiver, shares)
    Vault-->>User: emit Deposit(user, receiver, amount, shares)
```

**Key points:**

* `previewDeposit(assets)` returns the exact share count before committing.
* Shares are minted to `receiver`, which can differ from `msg.sender`.
* If `cap == 0` (default), deposits are unlimited.

### Queue-Based Redemption (No Fee)

Yield is **frozen at the moment `requestRedemption` is called.** No additional yield accrues during the lockup window.

```mermaid
sequenceDiagram
    actor User
    participant Vault as OpportunityOVault
    participant USDC as USDC Token

    User->>Vault: requestRedemption(shares)
    Note over Vault: Snapshot yieldFactorAtRequest = cumulativeRateFactor
    Note over Vault: ⚠️ YIELD FROZEN HERE — no yield accrues during lockup
    Vault->>Vault: transfer shares (user → vault, locked)
    Vault-->>User: emit RedemptionRequested(user, shares, unlockTime)

    Note over User,Vault: Wait ≥ lockupPeriod (default 5 min, configurable up to 365 days)

    User->>Vault: completeRedemption(receiver)
    Vault->>Vault: assets = shares × yieldFactorAtRequest / RAY / decimalOffset
    Vault->>Vault: _burn(vault, shares)
    Vault->>USDC: transfer(receiver, assets)
    Vault-->>User: emit RedemptionCompleted(user, receiver, shares, assets)
```

**Key points:**

* One active request per user — call `cancelRedemption()` first to open a second.
* `unlockTime` is set at request time from `block.timestamp + lockupPeriod`. A later admin change to `lockupPeriod` does not affect existing requests.
* There is no expiry — a completed request can wait indefinitely past `unlockTime`.
* `previewCompleteRedemption(user)` returns the payout for any pending request.

### Early Redemption (With Fee)

No lockup, uses live share value, fee stays in vault.

```mermaid
sequenceDiagram
    actor User
    participant Vault as OpportunityOVault
    participant USDC as USDC Token

    User->>Vault: redeemEarly(shares, receiver, minAssetsOut)
    Vault->>Vault: _updateRateFactor()
    Vault->>Vault: assetsBeforeFee = shares × cumulativeRateFactor / RAY / decimalOffset
    Vault->>Vault: fee = assetsBeforeFee × earlyRedemptionFee / 10000
    Vault->>Vault: assets = assetsBeforeFee − fee
    alt assets < minAssetsOut
        Vault-->>User: revert RedeemSlippageExceeded
    end
    Vault->>Vault: _burn(user, shares)
    Vault->>USDC: transfer(receiver, assets)
    Note over Vault: fee remains as surplus USDC in vault
    Vault-->>User: emit EarlyRedemption(user, receiver, shares, assets, fee)
```

**Key points:**

* `minAssetsOut = 0` disables slippage protection (the check `assets < 0` never fires for `uint256`). Pass a non-zero value to protect against a fee increase in the same block.
* Use `previewRedeemEarly(shares)` to get `(assets, fee)` before calling.

### Cross-Chain Share Bridge (OFT)

Vault shares are LayerZero V2 OFT tokens and can be bridged between any two deployed vaults via the standard OFT `send` interface.

```mermaid
sequenceDiagram
    actor User
    participant SrcVault as Vault — Source Chain
    participant LZ as LayerZero Network
    participant DstVault as Vault — Destination Chain

    User->>SrcVault: send(SendParam{dstEid, to, amount, ...}, fee, refundAddress)
    SrcVault->>SrcVault: burn shares on source chain
    SrcVault->>LZ: _lzSend(dstEid, OFT message, fees)
    Note over LZ: DVN verification + executor relay (~5–10 min)
    LZ->>DstVault: _lzReceive(message)
    DstVault->>DstVault: message.length ≤ 64 → route to OFT base
    DstVault->>DstVault: mint shares on destination chain
    DstVault-->>User: shares arrive on destination
```

**Key points:**

* Both the source and destination vault must have each other configured via `setPeer` (OApp) and `addPeerEndpoint` (state sync).
* Bridged shares represent the same claim — `convertToAssets` returns the same value on both chains once state is synced.
* The contract must hold ETH to pay LayerZero fees. Fund it via `address(vault).transfer(amount)` or by sending ETH to the `receive()` fallback.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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://docs.tropicalwater.xyz/operational/user-flows.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.
