# Margin Facet

### Overview

The Margin Facet provides the following key functionalities:

* **Add Margin:** Transfer deposited balance from a parent sub-account to a virtual account's allocated balance.
* **Add Margin to Next VA:** Pre-fund the next virtual account that will be created for a given isolation key, before the quote is even sent.
* **Remove Margin:** Deallocate and transfer margin from a virtual account back to its parent sub-account.
* **Emergency Recover Margin:** Recover funds from orphaned or lost virtual account addresses.

***

### addMargin()

Transfers deposited balance from a parent sub-account to a virtual account's allocated balance using `internalTransfer` on the Symmio core.

**Function Signature:**

```solidity
function addMargin(address virtualAccount, uint256 amount) external whenNotPaused nonReentrant onlyAccountOwner(virtualAccount);
```

**Parameters:**

* `virtualAccount`: The virtual account to add margin to.
* `amount`: The amount to transfer (in 18 decimals).

**Events:** `AddMargin(address virtualAccount, address parent, uint256 amount)`

***

### addMarginToNextVA()

Pre-funds the next virtual account that will be created for a given isolation key. This is useful for frontends that want to fund the virtual account before the sendQuote call creates it. The function predicts the address by checking the reuse pool first, then singleVAMode, then the next nonce.

The isolation type must be compatible with the sub-account's isolation type (e.g., POSITION sub-account can only pre-fund POSITION virtual accounts).

**Function Signature:**

```solidity
function addMarginToNextVA(
    address subAccount,
    VirtualAccountIsolationType isolationType,
    uint256 symbolId,
    uint256 amount
) external whenNotPaused nonReentrant onlyAccountOwner(subAccount);
```

**Parameters:**

* `subAccount`: The parent sub-account.
* `isolationType`: The virtual account isolation type to pre-fund.
* `symbolId`: The symbol ID for the target virtual account.
* `amount`: The amount to transfer (in 18 decimals).

**Events:** `AddMargin(address predictedVA, address subAccount, uint256 amount)`

***

### removeMargin()

Deallocates funds from a virtual account and transfers the balance back to its parent sub-account. Requires a Muon uPnL signature to verify solvency after deallocation.

**Function Signature:**

```solidity
function removeMargin(
    address virtualAccount,
    uint256 amount,
    ISymmio.SingleUpnlSig memory upnlSig
) external whenNotPaused nonReentrant onlyAccountOwner(virtualAccount);
```

**Parameters:**

* `virtualAccount`: The virtual account to remove margin from.
* `amount`: The amount to deallocate and transfer (in 18 decimals).
* `upnlSig`: The Muon signature proving the account's uPnL for solvency verification.

The function calls `deallocate` followed by `internalTransfer` on the Symmio core, moving funds from the virtual account back to the parent sub-account's allocated balance.

**Events:** `RemoveMargin(address virtualAccount, address parent, uint256 amount)`

***

### emergencyRecoverMargin()

Recovers funds from a lost or orphaned virtual account address back to the parent sub-account. This is used when a virtual account address has funds (from a pre-fund via `addMarginToNextVA` or `internalTransfer`) but was never formally created, or was orphaned due to an edge case.

The function deallocates any allocated balance (using `zeroUpnlDeallocate`, which requires no open positions) and then transfers the full balance to the parent via `internalTransferToBalance`.

**Function Signature:**

```solidity
function emergencyRecoverMargin(address subAccount, uint256 nonce) external whenNotPaused nonReentrant onlyAccountOwner(subAccount);
```

**Parameters:**

* `subAccount`: The parent sub-account to recover funds to.
* `nonce`: The nonce used to derive the lost virtual account address. Must be between 1 and the current nonce + 1.

**Preconditions:** The derived address must not be an existing sub-account or virtual account. It must have a non-zero balance or allocated balance.

**Events:** `EmergencyMarginRecovered(address lostAccount, address subAccount, uint256 totalBalance)`
