# Account Facet (0.8.4)

The **Account Facet** is the primary interface for managing collateral within the SYMM Diamond. It allows both PartyA and PartyB to deposit and withdraw collateral, allocate funds for trading, perform internal transfers, and interact with a reserve vault for hedgers. The underlying logic is implemented in the `AccountFacetImpl` library.

> **Note:**\
> Collateral amounts for deposit/withdraw functions are specified in the token's native decimals. Internally, allocations and transfers are normalized to 18 decimals. In addition, note the following key changes introduced in 0.8.4:
>
> * **Internal Transfer:** In this version, we've removed the `notPartyB` modifier on this method, allowing Party Bs to use it as well. Although Party Bs don't have multiple accounts to transfer between, they can use this method for a different purpose. Currently, Party Bs have balance manager processes that constantly monitor and allocate/deallocate funds for their users. This frequent activity resets their deallocate cooldown each time. With this new method, Party Bs can transfer some of their funds to a different account and let them remain there, allowing the cooldown period for that account to pass without interruption.
> * **Deallocate:** A new debounce check ensures that deallocation requests are not made too frequently.

***

### Overview

The **Account Facet** provides the following key functionalities:

* **Depositing Collateral:**\
  Party A or Party B can deposit collateral into the protocol, including on behalf of another user.
* **Withdrawing Collateral:**\
  Withdrawals are allowed once the cooldown period has elapsed.
* **Allocating Collateral:**\
  Moves funds from the free balance to the allocated balance, making them available for trading.
* **Deallocating Collateral:**\
  Returns allocated funds back to the free balance, with a debounce check to prevent frequent deallocations.
* **Internal Transfers:**\
  Transfers funds internally between accounts without waiting for the deallocate cooldown. (Now extended to Party Bs.)
* **Reserve Vault Operations:**\
  Enables hedgers to deposit and withdraw funds from a dedicated reserve vault used during force-close operations.

***

### deposit()

Deposits a specified amount of collateral into the protocol. The amount is provided in the token's native decimals and is normalized to 18 decimals internally.

**Function Signature:**

```solidity
function deposit(uint256 amount) external whenNotAccountingPaused;
```

**Parameters:**

* `amount`: The collateral amount to deposit (in native decimals).

**Example:**

```solidity
// Deposit 100 tokens into the protocol
symmDiamond.deposit(100);
```

**Events Emitted:**

* `Deposit(address sender, address user, uint256 amount)`

***

### depositFor()

Deposits collateral on behalf of another user.

**Function Signature:**

```solidity
function depositFor(address user, uint256 amount) external whenNotAccountingPaused;
```

**Parameters:**

* `user`: The recipient address.
* `amount`: The collateral amount to deposit (in native decimals).

**Example:**

```solidity
// Deposit 50 tokens on behalf of a user
symmDiamond.depositFor(recipientAddress, 50);
```

**Events Emitted:**

* `Deposit(address sender, address user, uint256 amount)`

***

### withdraw()

Withdraws a specified amount of collateral from the caller’s free balance after the cooldown period has elapsed.

**Function Signature:**

```solidity
function withdraw(uint256 amount) external whenNotAccountingPaused notSuspended(msg.sender);
```

**Parameters:**

* `amount`: The collateral amount to withdraw (in native decimals).

**Example:**

```solidity
// Withdraw 30 tokens from your balance
symmDiamond.withdraw(30);
```

**Events Emitted:**

* `Withdraw(address sender, address user, uint256 amount)`

***

### withdrawTo()

Withdraws collateral from the caller’s free balance and transfers it to another user’s address, subject to the cooldown restrictions.

**Function Signature:**

```solidity
function withdrawTo(address user, uint256 amount) external whenNotAccountingPaused notSuspended(msg.sender);
```

**Parameters:**

* `user`: The recipient address.
* `amount`: The collateral amount to withdraw (in native decimals).

**Example:**

```solidity
// Withdraw 25 tokens and send them to another user
symmDiamond.withdrawTo(otherUserAddress, 25);
```

**Events Emitted:**

* `Withdraw(address sender, address user, uint256 amount)`

***

### allocate()

Allocates a specified amount of collateral for trading by moving funds from the free balance to the allocated balance (expressed in 18 decimals). This allocated balance is the collateral considered for opening trades.

**Function Signature:**

```solidity
function allocate(uint256 amount) external whenNotAccountingPaused notSuspended(msg.sender) notLiquidatedPartyA(msg.sender);
```

**Parameters:**

* `amount`: The amount to allocate (in 18 decimals).

**Example:**

```solidity
// Allocate 50 tokens for trading (amount in 18 decimals)
symmDiamond.allocate(50 * 1e18);
```

**Events Emitted:**

* `AllocatePartyA(address user, uint256 amount, uint256 newAllocatedBalance)`
* `AllocatePartyA(address user, uint256 amount)` *(for backward compatibility, may be removed in subsequent versions)*
* `BalanceChangePartyA(msg.sender, amount, ALLOCATE)`

***

### depositAndAllocate()

Performs a combined deposit and allocation. The deposited amount (provided in native decimals) is converted to 18 decimals before being allocated.

**Function Signature:**

```solidity
function depositAndAllocate(uint256 amount) external whenNotAccountingPaused notLiquidatedPartyA(msg.sender) notSuspended(msg.sender);
```

**Parameters:**

* `amount`: The collateral amount to deposit and allocate (in native decimals).

**Example:**

```solidity
// Deposit and immediately allocate 100 tokens
symmDiamond.depositAndAllocate(100);
```

**Events Emitted:**

* `Deposit(address sender, address user, uint256 amount)`
* `AllocatePartyA(address user, uint256 amount, uint256 newAllocatedBalance)`
* `AllocatePartyA(address user, uint256 amount)` *(for backward compatibility)*
* `BalanceChangePartyA(msg.sender, amount, ALLOCATE)`

***

### deallocate()

Deallocates a specified amount of collateral, returning it to the free balance. This method now includes a debounce time check to prevent too frequent deallocation requests. Specifically, it requires that the current block timestamp is at greater than the user's last successful deallocate/withdraw plus the global `deallocateDebounceTime` (from `MAStorage`). The method also verifies that sufficient allocated balance is available and uses a Muon signature (`upnlSig`) to ensure that the deallocation maintains sufficient collateralization.

**Function Signature:**

```solidity
function deallocate(uint256 amount, SingleUpnlSig memory upnlSig) external whenNotAccountingPaused notLiquidatedPartyA(msg.sender);
```

**Parameters:**

* `amount`: The amount to deallocate (in 18 decimals).
* `upnlSig`: A `SingleUpnlSig` structure containing the Muon signature for verification.

**Example:**

```solidity
// Deallocate 40 tokens using a valid Muon signature, ensuring sufficient debounce time has elapsed
symmDiamond.deallocate(40 * 1e18, upnlSignature);
```

**Events Emitted:**

* `DeallocatePartyA(address user, uint256 amount, uint256 newAllocatedBalance)`
* `DeallocatePartyA(address user, uint256 amount)` *(for backward compatibility)*
* `BalanceChangePartyA(msg.sender, amount, DEALLOCATE)`

***

### internalTransfer()

Transfers funds from the caller’s free balance to another user’s allocated balance.

> **Internal Transfer for Party Bs:**\
> Previously, this function was limited to Party As. In 0.8.3 and beyond, the restriction is removed so that Party Bs can also utilize this method. Note that `internalTransfer()` operates on the sender's free balance (not the allocated balance). If funds are already allocated, you must first call `deallocate()` before transferring them. Additionally, the recipient address cannot be a Party B and must not be in a liquidated state.

**Function Signature:**

```solidity
function internalTransfer(address user, uint256 amount) external whenNotInternalTransferPaused userNotPartyB(user) notSuspended(msg.sender) notSuspended(user) notLiquidatedPartyA(user);
```

**Parameters:**

* `user`: The recipient address.
* `amount`: The amount to transfer (in 18 decimals).

**Example:**

```solidity
// Transfer 20 tokens from your free balance to another user's allocated balance.
// If funds are already allocated, deallocate them first.
symmDiamond.internalTransfer(recipientAddress, 20 * 1e18);
```

**Events Emitted:**

* `InternalTransfer(address sender, address user, uint256 userNewAllocatedBalance, uint256 amount)`
* (Additional events such as `Withdraw` and `AllocatePartyA` are emitted to reflect the resulting balance changes.)

***

### allocateForPartyB()

Allows Party B to allocate a specified amount of their free balance for a designated Party A. This function is used to establish trading relationships between Party B and Party A.

**Function Signature:**

```solidity
function allocateForPartyB(uint256 amount, address partyA) public whenNotPartyBActionsPaused notLiquidatedPartyB(msg.sender, partyA) onlyPartyB;
```

**Parameters:**

* `amount`: The amount to allocate (in 18 decimals).
* `partyA`: The Party A address for which the allocation is made.

**Example:**

```solidity
// Party B allocates 30 tokens for Party A
symmDiamond.allocateForPartyB(30 * 1e18, partyAAddress);
```

**Events Emitted:**

* `AllocateForPartyB(address partyB, address partyA, uint256 amount, uint256 newAllocatedBalance)`
* `AllocateForPartyB(address partyB, address partyA, uint256 amount)` *(for backward compatibility)*
* `BalanceChangePartyB(msg.sender, partyA, amount, ALLOCATE)`

***

### deallocateForPartyB()

Allows Party B to deallocate a specified amount of previously allocated collateral for a given Party A. A Muon signature (`upnlSig`) is required to ensure that the deallocation is safe and does not render the party liquidatable.

**Function Signature:**

```solidity
function deallocateForPartyB(uint256 amount, address partyA, SingleUpnlSig memory upnlSig) external whenNotPartyBActionsPaused notLiquidatedPartyB(msg.sender, partyA) notSuspended(msg.sender) notLiquidatedPartyA(partyA) onlyPartyB;
```

**Parameters:**

* `amount`: The amount to deallocate (in 18 decimals).
* `partyA`: The Party A address.
* `upnlSig`: A `SingleUpnlSig` structure containing the Muon signature for verification.

**Example:**

```solidity
// Party B deallocates 15 tokens for Party A using a valid Muon signature
symmDiamond.deallocateForPartyB(15 * 1e18, partyAAddress, upnlSignature);
```

**Events Emitted:**

* `DeallocateForPartyB(address partyB, address partyA, uint256 amount, uint256 newAllocatedBalance)`
* `DeallocateForPartyB(address partyB, address partyA, uint256 amount)` *(for backward compatibility)*
* `BalanceChangePartyB(msg.sender, partyA, amount, DEALLOCATE)`

***

### transferAllocation()

Transfers allocated collateral from one Party A (origin) to another Party A (recipient) within a Party B’s account. This function employs a Muon signature (`upnlSig`) for verification to ensure both parties remain solvent after the transfer.

**Function Signature:**

```solidity
function transferAllocation(uint256 amount, address origin, address recipient, SingleUpnlSig memory upnlSig) external whenNotPartyBActionsPaused;
```

**Parameters:**

* `amount`: The amount to transfer (in 18 decimals).
* `origin`: The PartyA address from which funds are transferred.
* `recipient`: The PartyA address to receive the funds.
* `upnlSig`: A `SingleUpnlSig` structure containing the Muon signature for verification.

**Example:**

```solidity
// Transfer 10 tokens from one Party A to another using a valid signature
symmDiamond.transferAllocation(10 * 1e18, originAddress, recipientAddress, upnlSignature);
```

**Events Emitted:**

* `TransferAllocation(uint256 amount, address origin, uint256 originNewAllocatedBalance, address recipient, uint256 recipientNewAllocatedBalance)`
* `TransferAllocation(uint256 amount, address origin, address recipient)` *(for backward compatibility)*
* Additional `BalanceChangePartyB` events indicate the deallocation from the origin and allocation to the recipient.

***

### depositToReserveVault()

**Description:**\
Transfers a specified amount of collateral from the caller’s free balance into an emergency reserve vault for hedgers.

> **Reserve Vault for Hedgers:**\
> Hedgers can deposit funds into a reserve vault that is not tied to any specific Party A. These funds are used exclusively during force-close operations, helping protect hedgers from liquidation when they might otherwise become insolvent.

**Function Signature:**

```solidity
function depositToReserveVault(uint256 amount, address partyB) external whenNotPartyBActionsPaused notSuspended(msg.sender) notSuspended(partyB);
```

**Parameters:**

* `amount`: The amount to deposit (in 18 decimals).
* `partyB`: The Party B address associated with the reserve vault.

**Example:**

```solidity
// Deposit 20 tokens into the reserve vault for a hedger (Party B)
symmDiamond.depositToReserveVault(20 * 1e18, partyBAddress);
```

**Events Emitted:**

* `DepositToReserveVault(address sender, address partyB, uint256 amount)`

***

### withdrawFromReserveVault()

Withdraws a specified amount of collateral from the caller’s emergency reserve vault back to their free balance.

> **Reserve Vault for Hedgers:**\
> Only Party B (hedgers) can withdraw from the reserve vault. This function provides quick access to funds during emergency scenarios.

**Function Signature:**

```solidity
function withdrawFromReserveVault(uint256 amount) external whenNotPartyBActionsPaused notSuspended(msg.sender) onlyPartyB;
```

**Parameters:**

* `amount`: The amount to withdraw (in 18 decimals).

**Example:**

```solidity
// Party B withdraws 20 tokens from the reserve vault to their free balance
symmDiamond.withdrawFromReserveVault(20 * 1e18);
```

**Events Emitted:**

* `WithdrawFromReserveVault(address partyB, uint256 amount)`
