# MultiAccount

## MultiAccount (0.8.4)

The MultiAccount module enables users to create sub‑accounts that are whitelisted to interact with hedgers. These sub‑accounts allow positions to be either in cross (all positions sharing collateral) or isolated (separate sub‑accounts). In addition to standard account creation and fund management, MultiAccount introduces robust access delegation features. In version 0.8.4, a key update is the two‑step revocation process for delegated access.

> **New Revocation Process:**\
> In earlier versions, users could revoke delegated access instantly. However, this sometimes led hedgers to execute actions (like sending quotes on behalf of users) only to have their access revoked unexpectedly. Now, users must first **propose** revocation using the `proposeToRevokeAccesses` method. After a configured cooldown period elapses, they can then **revoke** the access with the `revokeAccesses` method. This ensures that hedgers have advanced notice before their access is removed.

### Initialization and Setup

### initialize()

Initializes the MultiAccount contract with the necessary roles and addresses. It sets the administrator, the address of the Symmio platform, and the bytecode for the account implementation.

**Function Signature:**

```solidity
function initialize(address admin, address symmioAddress_, bytes memory accountImplementation_) public initializer;
```

**Parameters:**

* **`admin`:** The administrator’s address (granted default admin, pauser, unpauser, and setter roles).
* **`symmioAddress_`:** The address of the Symmio platform.
* **`accountImplementation_`:** The bytecode for the account implementation to be used for deploying sub‑accounts.

**Example Usage:**

```solidity
multiAccount.initialize(adminAddress, symmioPlatformAddress, accountImplBytecode);
```

***

### Account Management

### addAccount()

Creates a new sub‑account for the caller with a specified name. Each new account is deployed using the current account implementation and is mapped to the owner’s address.

**Function Signature:**

```solidity
function addAccount(string memory name) external whenNotPaused;
```

**Parameters:**

* **name:** The name of the new sub‑account.

**Example Usage:**

```solidity
multiAccount.addAccount("My Trading Account");
```

**Events Emitted:**

* `AddAccount(address owner, address account, string name)`

***

### editAccountName()

Allows the owner to change the name of an existing sub‑account.

**Function Signature:**

```solidity
function editAccountName(address accountAddress, string memory name) external whenNotPaused;
```

**Parameters:**

* **accountAddress:** The address of the sub‑account to rename.
* **name:** The new name for the account.

**Example Usage:**

```solidity
multiAccount.editAccountName(accountAddress, "Updated Account Name");
```

**Events Emitted:**

* `EditAccountName(address owner, address account, string newName)`

***

### depositForAccount()

Deposits funds into a sub‑account from the owner’s balance. It calls the Symmio platform’s deposit function on behalf of the account.

**Function Signature:**

```solidity
function depositForAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused;
```

**Parameters:**

* **account:** The address of the sub‑account.
* **amount:** The amount to deposit.

**Example Usage:**

```solidity
multiAccount.depositForAccount(accountAddress, 1000);
```

**Events Emitted:**

* `DepositForAccount(address owner, address account, uint256 amount)`

***

### depositAndAllocateForAccount()

Deposits funds into a sub‑account and immediately allocates them for trading. The deposited amount is converted to 18 decimals before being allocated.

**Function Signature:**

```solidity
function depositAndAllocateForAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused;
```

**Parameters:**

* **account:** The address of the sub‑account.
* **amount:** The amount to deposit and allocate.

**Example Usage:**

```solidity
multiAccount.depositAndAllocateForAccount(accountAddress, 1000);
```

**Events Emitted:**

* `DepositForAccount(address owner, address account, uint256 amount)`
* `AllocateForAccount(address owner, address account, uint256 amountWith18Decimals)`

***

### withdrawFromAccount()

Withdraws funds from a sub‑account back to the owner’s address. It calls the Symmio platform’s withdrawal function.

**Function Signature:**

```solidity
function withdrawFromAccount(address account, uint256 amount) external onlyOwner(account, msg.sender) whenNotPaused;
```

**Parameters:**

* **account:** The address of the sub‑account.
* **amount:** The amount to withdraw.

**Example Usage:**

```solidity
multiAccount.withdrawFromAccount(accountAddress, 500);
```

**Events Emitted:**

* `WithdrawFromAccount(address owner, address account, uint256 amount)`

***

## Access Delegation and Revocation

### delegateAccess()

**Description:**\
Allows the owner of a sub‑account to delegate access to a target address for a specific function. This enables external addresses (such as hedgers) to perform actions on behalf of the sub‑account.

**Function Signature:**

```solidity
function delegateAccess(address account, address target, bytes4 selector) external onlyOwner(account, msg.sender);
```

**Parameters:**

* **account:** The address of the sub‑account.
* **target:** The target contract address for which access is delegated.
* **selector:** The function selector (first 4 bytes of the function signature) for which access is granted.

**Example Usage:**

```solidity
bytes4 selector = bytes4(keccak256("sendQuote(uint256)"));
multiAccount.delegateAccess(accountAddress, hedgerAddress, selector);
```

**Events Emitted:**

* `DelegateAccess(address account, address target, bytes4 selector, bool state)` (state will be `true`)

***

### delegateAccesses()

Batch version of `delegateAccess`. Delegates access for multiple function selectors at once.

**Function Signature:**

```solidity
function delegateAccesses(address account, address target, bytes4[] memory selector) external onlyOwner(account, msg.sender);
```

**Parameters:**

* **account:** The sub‑account address.
* **target:** The target contract address.
* **selector:** An array of function selectors to delegate access for.

**Example Usage:**

```solidity
bytes4[] memory selectors = new bytes4[](2);
selectors[0] = bytes4(keccak256("sendQuote(uint256)"));
selectors[1] = bytes4(keccak256("withdraw(uint256)"));
multiAccount.delegateAccesses(accountAddress, hedgerAddress, selectors);
```

**Events Emitted:**

* `DelegateAccesses(address account, address target, bytes4[] selectors, bool state)` (state will be `true`)

***

### proposeToRevokeAccesses()

Proposes revoking delegated access from a target address for one or more function selectors. The proposal timestamp is recorded. Revocation does not take effect immediately; it only becomes actionable after the cooldown period.

**Function Signature:**

```solidity
function proposeToRevokeAccesses(address account, address target, bytes4[] memory selector) external onlyOwner(account, msg.sender);
```

**Parameters:**

* **account:** The sub‑account address.
* **target:** The target contract address from which access is to be revoked.
* **selector:** An array of function selectors for which revocation is proposed.

**Example Usage:**

```solidity
multiAccount.proposeToRevokeAccesses(accountAddress, hedgerAddress, selectors);
```

**Events Emitted:**

* `ProposeToRevokeAccesses(address account, address target, bytes4[] selectors)`

***

### revokeAccesses()

After the revoke cooldown period has elapsed, this function allows the owner to revoke delegated access for the specified function selectors from a target address.

**Function Signature:**

```solidity
function revokeAccesses(address account, address target, bytes4[] memory selector) external onlyOwner(account, msg.sender);
```

**Parameters:**

* **account:** The sub‑account address.
* **target:** The target contract address from which access will be revoked.
* **selector:** An array of function selectors to revoke.

**Example Usage:**

```solidity
multiAccount.revokeAccesses(accountAddress, hedgerAddress, selectors);
```

**Events Emitted:**

* `DelegateAccesses(address account, address target, bytes4[] selectors, bool state)` (state will be `false`)

***

### setRevokeCooldown()

Sets the cooldown period for the revocation process. This determines how long after proposing revocation the owner must wait before actually revoking access.

**Function Signature:**

```solidity
function setRevokeCooldown(uint256 cooldown) external onlyRole(SETTER_ROLE);
```

**Parameters:**

* **cooldown:** The new cooldown period in seconds.

**Example Usage:**

```solidity
multiAccount.setRevokeCooldown(300); // Set cooldown to 300 seconds (5 minutes)
```

**Events Emitted:**

* `SetRevokeCooldown(uint256 oldCooldown, uint256 newCooldown)`

***

## Configuration and Address Management

### setAccountImplementation()

Updates the bytecode for the account implementation used to deploy new sub‑accounts.

**Function Signature:**

```solidity
function setAccountImplementation(bytes memory accountImplementation_) external onlyRole(SETTER_ROLE);
```

**Parameters:**

* **accountImplementation\_:** The new account implementation bytecode.

**Example Usage:**

```solidity
multiAccount.setAccountImplementation(newAccountImplBytecode);
```

**Events Emitted:**

* `SetAccountImplementation(bytes oldImplementation, bytes newImplementation)`

***

### setSymmioAddress()

Updates the address of the Symmio platform with which the MultiAccount contract interacts.

**Function Signature:**

```solidity
function setSymmioAddress(address addr) external onlyRole(SETTER_ROLE);
```

**Parameters:**

* **addr:** The new Symmio platform address.

**Example Usage:**

```solidity
multiAccount.setSymmioAddress(newSymmioAddress);
```

**Events Emitted:**

* `SetSymmioAddress(address oldAddress, address newAddress)`

***

## Internal Functions

### \_deployPartyA()

Deploys a new Party A sub‑account using the current account implementation and a unique salt (via create2).

**Function Signature:**

```solidity
function _deployPartyA() internal returns (address account);
```

**Example:**\
This function is called internally by `addAccount`.

***

### \_deployContract()

Deploys a contract using the create2 opcode with the specified bytecode and salt.

**Function Signature:**

```solidity
function _deployContract(bytes memory bytecode, bytes32 salt) internal returns (address contractAddress);
```

**Example:**\
Called by `_deployPartyA` to deploy a new sub‑account.

***

## Pausable Functionality

### pause() / unpause()

Allows authorized users (with PAUSER\_ROLE/UNPAUSER\_ROLE) to pause or unpause the MultiAccount contract, halting or resuming all operations.

**Function Signatures:**

```solidity
function pause() external onlyRole(PAUSER_ROLE);
function unpause() external onlyRole(UNPAUSER_ROLE);
```

**Example Usage:**

```solidity
multiAccount.pause();
multiAccount.unpause();
```

***

## View Functions

#### getAccountsLength()

**Description:**\
Returns the number of sub‑accounts owned by a specific user.

**Function Signature:**

```solidity
function getAccountsLength(address user) external view returns (uint256);
```

**Example Usage:**

```solidity
uint256 numAccounts = multiAccount.getAccountsLength(userAddress);
```

***

### getAccounts()

Retrieves an array of sub‑accounts owned by a user, with pagination parameters.

**Function Signature:**

```solidity
function getAccounts(address user, uint256 start, uint256 size) external view returns (Account[] memory);
```

**Parameters:**

* **user:** The owner’s address.
* **start:** The starting index.
* **size:** The number of accounts to return.

**Example Usage:**

```solidity
Account[] memory userAccounts = multiAccount.getAccounts(userAddress, 0, 10);
```

***
