# Asset Managers

## Overview

Arcadia Accounts offer users the flexibility to delegate control of their assets to third-party Asset Managers. Asset Managers are smart contracts that execute specific strategies on behalf of an account owner, such as rebalancing or compounding liquidity positions. By leveraging Asset Managers, users can optimize the performance of their accounts while maintaining control over the delegation process.

## Key Features

1. **Delegation:** Users can authorize an Asset Manager to perform actions on their behalf.
2. **Full Access:** The Asset Manager has access to all assets within the assigned Arcadia Account.
3. **Flexible Strategies:** Asset Managers can perform complex operations, such as rebalancing or interacting with DeFi protocols.
4. **Health Check for Margin Accounts:** Asset Managers must ensure that a margin account remains in a healthy state after executing actions.
5. **Spot Accounts:** No health check is required for operations on spot accounts.

## Workflow

### 1. Setting an Asset Manager

The account owner assigns an Asset Manager to their account by calling the `setAssetManager()` function:

```
account.setAssetManager(assetManager, true);
```

* **Parameters:**
  * `assetManager`: Address of the Asset Manager contract.
  * `true`: Enables the Asset Manager.

Once set, the Asset Manager can perform actions using the `flashAction()` function.

### 2. Performing a Flash Action

The `flashAction()` function enables Asset Managers to execute complex operations. It allows the chaining of multiple actions in a single transaction, with the following capabilities:

* **Withdraw Assets:** Transfer assets from the Arcadia Account to the `actionTarget`.
* **Direct Transfers:** Transfer assets directly from the account owner to the `actionTarget`.
* **Execute External Logic:** Interact with DeFi protocols via the `actionTarget` (e.g., staking, swapping, or claiming rewards).
* **Deposit Back:** Deposit the resultant tokens back into the Arcadia Account.

At the end of the flash action, a health check ensures the margin account remains solvent (collateral value > liabilities). If the check fails, the transaction reverts.

#### Flash Action Parameters

```
flashAction(
    address actionTarget,
    bytes memory actionData
);
```

* `actionTarget`**:** The contract address where external logic is executed.
* `actionData`**:** Encoded data containing:
  * `withdrawData`: Asset withdrawal details from the Arcadia Account to the actionTarget.
  * `transferFromOwnerData`: Asset transfer details from the owner to the actionTarget.
  * `permit`: Permit for the Permit2 transfer.
  * `signature`: Signature for the Permit2 transfer.
  * `actionTargetData`: The encoded calldata required to perform the series of contract calls needed to execute a specific action or operation with the assets.

#### How Chaining of Calls Works

The `flashAction()` function enables chaining by executing a series of tightly coupled operations in a single transaction. Here’s a step-by-step breakdown:

1. **Decoding Input Data:** The function decodes the `actionData` input into its respective components:
   * Withdrawal details (`withdrawData`)
   * Transfer details (`transferFromOwnerData`)
   * Permit details for `Permit2`
   * Action target logic (`actionTargetData`)
2. **Asset Withdrawal:** Using `_withdraw()`, assets are transferred from the Arcadia Account to the `actionTarget` based on the `withdrawData`.
3. **Direct Transfers:** If `transferFromOwnerData` specifies additional assets, `_transferFromOwner()` transfers them from the owner’s wallet to the `actionTarget`.
4. **Permit-Based Transfers:** If a `signature` and `permit` are provided, `_transferFromOwnerWithPermit()` is called to initiate a `Permit2`-based asset transfer.
5. **External Logic Execution:** The Asset Manager calls `executeAction()` on the `actionTarget`, passing the `actionTargetData` to interact with external protocols (e.g., swapping tokens, staking).
6. **Deposit Back to Account:** After executing external logic, `_deposit()` transfers the resulting assets back into the Arcadia Account. The `_deposit()` function uses `depositData`, which is returned from the `executeAction()` call on the `actionTarget`, to determine the assets and amounts to deposit.
7. **Health Check (Margin Accounts Only):** The `isAccountUnhealthy()` function ensures the margin account remains solvent. If not, the transaction reverts.

## Interfaces for Asset Managers

To interact with the `flashAction()` function, developers must implement the following interfaces:

```
// Struct with information to pass to and from the actionTarget.
struct ActionData {
    // Array of the contract addresses of the assets.
    address[] assets;
    // Array of the IDs of the assets.
    uint256[] assetIds;
    // Array with the amounts of the assets.
    uint256[] assetAmounts;
    // Array with the types of the assets.
    uint256[] assetTypes;
}

interface IActionBase {
    /**
     * @notice Calls an external target contract with arbitrary calldata.
     * @param actionTargetData A bytes object containing the encoded input for the actionTarget.
     * @return resultData An ActionData struct with the final balances of this actionTarget contract.
     */
    function executeAction(bytes calldata actionTargetData) external returns (ActionData memory);
}
```

### Requirements for Asset Managers

An Asset Manager should implement the following steps to function correctly:

1. **Call `flashAction()` on the Account:**
   * The Asset Manager must call the `flashAction()` function on the Arcadia Account.
   * The input to `flashAction()` includes:
     * The address of the `actionTarget` contract.
     * Encoded `actionData`, which must be formatted as follows:

       ```
       (
           ActionData memory withdrawData,
           ActionData memory transferFromOwnerData,
           IPermit2.PermitBatchTransferFrom memory permit,
           bytes memory signature,
           bytes memory actionTargetData
       ) = abi.decode(actionData, (ActionData, ActionData, IPermit2.PermitBatchTransferFrom, bytes, bytes));
       ```
2. **Implement `executeAction()` in the ActionTarget Contract:**
   * The `actionTarget` contract must include an `executeAction()` function that:
     * Accepts `actionTargetData` as input.
     * Executes all the required logic to perform the desired operation or strategy.
     * Returns an `ActionData` struct that contains the addresses and amounts of assets to be deposited back into the Arcadia Account.
3. **Handle the Returned Data:**
   * The `ActionData` struct returned by `executeAction()` is used to call `_deposit()` and finalize the process by returning the assets to the Arcadia Account.
