> For the complete documentation index, see [llms.txt](https://docs.symm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.symm.io/options-protocol-architecture/technical-architecture/balance-operations-deposit-withdraw-transfers.md).

# Balance Operations (Deposit, Withdraw, Transfers)

The Symmio deposit and withdraw system lets users deposit collateral, initiate withdrawals, and optionally take express withdrawals from their isolated balances.

Standard withdrawals can be subject to a cooldown period, during which the requested funds are locked. To skip that delay, a user can request an express withdrawal through a registered liquidity provider, usually for a fee, and get faster access to the funds.

### Deposit

Users deposit collateral into their isolated balance with `deposit`. The call handles internal accounting, enforces system constraints, and optionally transfers ERC-20 tokens from the user's wallet.

```
deposit(address collateral, uint256 amount) // user = msg.sender

depositFor(address collateral, address user, uint256 amount)
```

On invocation, the function:

* Validates that the `collateral` token is whitelisted.
* Ensures `amount` is greater than zero and `user` is a valid address.
* Verifies the deposit won't exceed `balanceLimitPerUser`.
* Normalizes `amount` to 18 decimals for internal consistency.
* Increases the user's isolated balance.
* Transfers tokens from the user's wallet to the protocol if `doTransfer` is `true`.

Note: `virtualDepositFor` updates a balance *without* transferring the actual collateral. Only addresses granted `VIRTUAL_DEPOSITOR_ROLE` can call it.

### Withdraw

Withdrawing from an isolated balance is a two-phase process, initiation then completion, with a cooldown period between the two phases to harden the protocol against abuse and malicious withdrawal attempts.

Symmio also supports express withdrawals through approved third-party express providers. A provider pre-funds the user's withdrawal amount immediately for a fee, then collects the actual withdrawal from the protocol after the cooldown ends. The user skips the wait, and the provider takes on the risk of delayed settlement or a security-based withdrawal failure.

#### 1. Initiate withdraw

Request a withdrawal with one of:

```
function initiateWithdraw(address collateral, uint256 amount, address to)
```

```
function initiateExpressWithdraw(
address collateral,
uint256 amount,
address to,
address provider,
bytes memory userData
)
```

**Parameters:**

* `collateral`: the ERC-20 token to withdraw.
* `amount`: amount to withdraw, in collateral decimals.
* `to`: destination address for the funds.
* `provider`: registered express withdrawal provider.
* `userData`: arbitrary data passed to the provider for validation (express withdrawals).

**Behavior:**

* Validates that the sender has enough available (unlocked) balance.
* Verifies solvency and per-user balance limits.
* Immediately deducts the withdrawal amount from the user's isolated balance.
* Creates a `Withdraw` object with status `INITIATED`.

If a provider is specified, it also ensures the provider is registered and active, calls `validateWithdraw(...)` on the provider contract, and records the provider metadata in the `Withdraw` object.

#### 2. Complete withdraw

Once the cooldown has elapsed, finalize the withdrawal:

```
function completeWithdraw(uint256 id)
```

To read the current cooldown durations, call:

* `getPartyADeallocateCooldown` for PartyA:
* `getPartyBDeallocateCooldown` for PartyB:

```
function getPartyADeallocateCooldown() external view returns (uint256)
```

```
function getPartyBDeallocateCooldown() external view returns (uint256)
```

The final destination depends on whether a provider was used. With an express provider, funds go to the provider's configured `receiver`; otherwise they go to the original `to` address. The function then sets the `Withdraw` status to `COMPLETED`.

**Cancel withdraw (non-express only)**

```
function cancelWithdraw(uint256 id)
```

Allowed only when no express provider was specified. Restores the withdrawn amount to the user's isolated balance and marks the request `CANCELED`.

**Suspend and restore**

These admin functions handle invalid or disputed withdrawals.

```
function suspendWithdraw(uint256 id)
```

```
function restoreWithdraw(uint256 id, uint256 validAmount)
```

`suspendWithdraw` marks the withdrawal `SUSPENDED`. `restoreWithdraw` returns `validAmount` to the user and sends any excess to the system-owned `invalidWithdrawalsAmountsPool`.

### Express withdraw system

The express withdrawal system lets external providers pre-fund user withdrawals in exchange for liquidity fees or execution spreads, giving instant withdrawals that bypass the standard cooldown.

**Provider requirements**

To be eligible, an express withdrawal provider must:

* Implement the `IExpressWithdrawProvider` interface.
* Be registered with `isActive == true` and a valid, non-zero `receiver` address.
* Implement `validateWithdraw(...)` to enforce any custom logic or verification.

If validation fails, the protocol reverts with:

```
ExpressWithdrawRejectedByProvider(provider, reason)
```

**Final fund flow (with provider)**

When a provider is used, the actual protocol withdrawal funds are sent to the provider's receiver address, and the provider funds the user immediately (typically off-chain or through liquidity routing).

### Internal transfer

`internalTransfer` moves collateral directly from a user's available Symmio balance to another user's isolated balance within the same protocol (for example, Symmio Options).

```
internalTransfer(address collateral, address user, uint256 amount)
```

This function transfers collateral from the sender (`msg.sender`) to the recipient `user` inside the Symmio system. It moves no tokens externally, only updating internal accounting, and enforces security and solvency checks for both sender and receiver.

**Validation and behavior**

* Verifies that `amount` is greater than zero.
* Ensures the recipient `user` address is not zero.
* Checks that neither party is suspended or paused.
* Validates that the sender has enough available balance (excluding locked funds).
* Enforces the receiver's balance cap (`balanceLimitPerUser`) if the receiver is not PartyB.
* Emits an `InternalTransfer` event with pre- and post-transfer balances.

Restrictions: can't be used by PartyB accounts, or when the protocol is in instant mode, or when internal transfers are paused.

### External transfer

`externalTransfer` moves collateral from a user's Symmio balance to a whitelisted external target contract, such as another Symmio service (for example, Symmio Perpetuals or Lending). It gives instant, cooldown-free transfers across Symmio subsystems.

```
externalTransfer(address collateral, address user, uint256 amount, address target)
```

This function:

* Transfers collateral from `msg.sender` to a designated external system (for example, from Options to Perpetuals).
* Skips any withdrawal delay or cooldown.
* Performs both the internal balance deduction and the ERC-20 token transfer.
* Notifies the receiving contract through a standardized callback.

**Validation and behavior**

* Requires a non-zero `amount`, `user`, and `target` address.
* Ensures the `target` contract is whitelisted for the collateral.
* Subtracts the amount from the sender's isolated balance.
* Converts internal units (18 decimals) to the token's native decimals.
* Performs an ERC-20 transfer to the `target` contract.
* Invokes `onTransfer` on the `target` contract for integration handling.
* Emits an `ExternalTransfer` event.

Use cases: instant liquidity movement between Symmio Options and Symmio Perps, and transfers between isolated product-specific accounts without a user withdrawal.

Restrictions: the sender must not be suspended or paused, transfers are allowed only to whitelisted target contracts, and this can't be used when external transfers are paused.


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.symm.io/options-protocol-architecture/technical-architecture/balance-operations-deposit-withdraw-transfers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
