> ## Documentation Index
> Fetch the complete documentation index at: https://thrackle.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Account Max Value Out By Access Level

> Enforces limits on value transferred out of economy based on access level

export const RuleApplicabilityLegend = ({tokens, actions}) => {
  return <AccordionGroup>
      <Accordion title="Applies to Tokens" icon="sliders-up">
        <CardGroup cols={4}>
          <Card title="ERC-20" icon={tokens.erc20 ? `square-check` : `square-xmark`} iconType="solid" color={tokens.erc20 ? `#57be39` : `gray`} horizontal />
          <Card title="ERC-721" icon={tokens.erc721 ? `square-check` : `square-xmark`} iconType="solid" color="#57be39" horizontal />
        </CardGroup>
      </Accordion>
      <Accordion title="Applies to Actions" icon="sliders">
        <CardGroup cols={4}>
          <Card title="MINT" icon={actions.mint ? `square-check` : `square-xmark`} iconType="solid" color={actions.mint ? `#57be39` : `gray`} horizontal />
          <Card title="BURN" icon={actions.burn ? `square-check` : `square-xmark`} iconType="solid" color={actions.burn ? `#57be39` : `gray`} horizontal />
          <Card title="BUY" icon={actions.buy ? `square-check` : `square-xmark`} iconType="solid" color={actions.buy ? `#57be39` : `gray`} horizontal />
          <Card title="SELL" icon={actions.sell ? `square-check` : `square-xmark`} iconType="solid" color={actions.sell ? `#57be39` : `gray`} horizontal />
        </CardGroup>
        <Card title="TRANSFER (Peer to Peer)" icon={actions.transfer ? `square-check` : `square-xmark`} iconType="solid" color={actions.transfer ? `#57be39` : `gray`} horizontal />
      </Accordion>
    </AccordionGroup>;
};

## Purpose

The purpose of this rule is to provide limits on the amount of funds that an account can remove from the application's economy based on an application defined segment of users.

The segments are defined as the access levels of the accounts. This rule may be used to provide gated withdrawal limits of assets to ensure accounts cannot withdraw more US Dollars or chain native tokens without first performing other actions defined by the application.

For example, the application may prevent users from withdrawing prior to performing specific onboarding activities. The application developer may set a very restrictive withdraw limit of `$0` for the default access level and `$1000` (or any other arbitrary amount) for the next access level.

As accounts are introduced to the ecosystem, they may not withdraw from the ecosystem until their access level increases.

<Note>
  This rule does not prevent the accumulation of protocol supported assets.
</Note>

<RuleApplicabilityLegend tokens={{ erc20: true, erc721: true }} actions={{ burn: true, sell: true, transfer: true }} />

## Scope

This rule works at the application level which means that all tokens in the app will have no choice but to comply with this rule when active.

## Data Structure

A withdrawal-by-access-level rule is composed of a single variable:

* **withdrawalLimit** (mapping(uint8 =>uint48)): the maximum USD worth of application assets that accounts can withdraw per access level.

```c
 mapping(uint8 => uint48);
```

###### *see [IRuleStorage](/v1/reference/protocol/economic/ruleProcessor/IRuleStorage.sol/interface.IRuleStorage)*

***NOTE: access levels are restricted from 0 to 4.***

These rules are stored in a mapping indexed by ruleId(uint32) in order of creation:

```c
/// Account Max Value Out by Access Level
    struct AccountMaxValueOutByAccessLevelS {
        /// ruleIndex => access level => max
        mapping(uint32 => mapping(uint8 => uint48)) accountMaxValueOutByAccessLevelRules;
        uint32 accountMaxValueOutByAccessLevelIndex;
    }
```

###### *see [IRuleStorage](/v1/reference/protocol/economic/ruleProcessor/IRuleStorage.sol/interface.IRuleStorage)*

## Configuration and Enabling/Disabling

* This rule can only be configured in the protocol by a **rule administrator**.
* This rule can only be set in the application handler by a **rule administrator**.
* This rule can only be activated/deactivated in the application handler by a **rule administrator**.
* This rule can only be updated in the application handler by a **rule administrator**.

## Rule Evaluation

The rule will be evaluated with the following logic:

1. The handler determines if the rule is active from the supplied action. If not, processing does not continue past this step.
2. The application manager sends to the protocol's rule processor the dollar value sum of all application assets the account has already withdrawn, the access level of the account, the ruleId, and the dollar amount to be transferred in the transaction.
3. The processor retrieves the maximum withdrawal limit allowed for the rule with the ruleId passed, and for the access level of the account. If the withdrawal amount plus already withdrawn amount exceeds the maximum allowed by the rule in the case of a successful transactions, then the transaction reverts.
4. If it's a non-custodial style [Buy](/v1/rules/action-types#buy)
   1. When the [Sell](/v1/rules/action-types#sell) action is also active, checks steps 1-3 for from address.

**The list of available actions rules can be applied to can be found at [ACTION\_TYPES](/v1/rules/action-types)**

###### *see [ApplicationAccessLevelProcessorFacet](/v1/reference/protocol/economic/ruleProcessor/ApplicationAccessLevelProcessorFacet.sol/contract.ApplicationAccessLevelProcessorFacet) -> checkeithdrawalLimitsByAccessLevel*

## Evaluation Exceptions

* This rule doesn't apply when a **treasuryAccount** address is in either the *from* or the *to* side of the transaction. This doesn't necessarily mean that if an treasury account is the one executing the transaction it will bypass the rule, unless the aforementioned condition is true.

### Revert Message

The rule processor will revert with the following error if the rule check fails:

```
error OverMaxValueOutByAccessLevel();
```

The selector for this error is `0x8d857c50`.

## Create Function

Adding a withdrawal-by-access-level rule is done through the function:

```c
function addAccountMaxValueOutByAccessLevel(
            address _appManagerAddr,
            uint48[] calldata _withdrawalAmounts
        )
        external
        ruleAdministratorOnly(_appManagerAddr)
        returns (uint32);
```

###### *see [AppRuleDataFacet](/v1/reference/protocol/economic/ruleProcessor/AppRuleDataFacet.sol/contract.AppRuleDataFacet)*

The add function will return the protocol ID of the rule.

### Parameters:

* **\_appManagerAddr** (address): the address of the application manager to verify that the caller has rule administrator privileges.
* **\_withdrawalAmounts** (uint48\[]): array of withdrawal limits for each 5 levels (levels 0 to 4) in whole USD amounts (1 -> 1 USD; 1000 -> 1000 USD). Note that the position within the array matters. Position 0 represents access level 0, and position 4 represents level 4.

### Parameter Optionality:

There are no options for the parameters of this rule.

### Parameter Validation:

The following validation will be carried out by the add function in order to ensure that these parameters are valid and make sense:

* The `_withdrawalAmounts` array has length 5.
* The elements of the `_withdrawalAmounts` array are in ascending order.

###### *see [AppRuleDataFacet](/v1/reference/protocol/economic/ruleProcessor/AppRuleDataFacet.sol/contract.AppRuleDataFacet)*

## Other Functions:

* In Protocol [Rule Processor](/v1/reference/protocol/economic/ruleProcessor/ApplicationAccessLevelProcessorFacet.sol/contract.ApplicationAccessLevelProcessorFacet):
  * Function to get a rule by its Id:
    ```c
    function getAccountMaxValueOutByAccessLevel(uint32 _index, uint8 _accessLevel) external view returns (uint48);
    ```
  * Function to get current amount of rules in the protocol:
    ```c
    function getTotalAccountMaxValueOutByAccessLevel() external view returns (uint32);
    ```
* In Protocol [Rule Processor](/v1/reference/protocol/economic/ruleProcessor/ApplicationAccessLevelProcessorFacet.sol/contract.ApplicationAccessLevelProcessorFacet):
  * Function that evaluates the rule:
    ```c
    function checkAccountMaxValueOutByAccessLevel(
                uint32 _ruleId,
                uint8 _accessLevel,
                uint128 _usdWithdrawalTotal,
                uint128 _usdAmountTransferring
            )
            external
            view;
    ```
* In the [Application Handler](/v1/reference/client/application/ProtocolApplicationHandler.sol/contract.ProtocolApplicationHandler):
  * Function to set and activate at the same time the rule for the supplied actions in the application handler:
    ```c
    function setAccountMaxValueOutByAccessLevelId(ActionTypes[] calldata _actions, uint32 _ruleId) external ruleAdministratorOnly(appManagerAddress);
    ```
  * Function to atomically set and activate at the same time the rule for the supplied actions in the application handler:
    ```c
    function setAccountMaxValueOutByAccessLevelIdFull(ActionTypes[] calldata _actions, uint32[] calldata _ruleIds) external ruleAdministratorOnly(appManagerAddress);
    ```
  * Function to activate/deactivate the rule for the supplied actions in the application handler:
    ```c
    function activateAccountMaxValueOutByAccessLevel(ActionTypes[] calldata _actions, bool _on) external ruleAdministratorOnly(appManagerAddress);
    ```
  * Function to know the activation state of the rule for the supplied action in an asset handler:
    ```c
    function isAccountMaxValueOutByAccessLevelActive(ActionTypes _action) external view returns (bool);
    ```
  * Function to get the rule Id for the supplied action from the application handler:
    ```c
    function getAccountMaxValueOutByAccessLevelId(ActionTypes _action) external view returns (uint32);
    ```

## Return Data

This rule returns 1 value:

1. **Accumulated US Dollar Amount Withdrawn** (uint128): the updated value for the total US Dollar amount of withdrawn per account.

```c
mapping(address => uint128) usdValueTotalWithrawals;
```

\*see [ProtocolApplicationHandler](/v1/reference/client/application/ProtocolApplicationHandler.sol/contract.ProtocolApplicationHandler)

## Data Recorded

This rule requires recording of the following information in the application handler:

```c
    /// Account Max Value Out by Access Level data
    mapping(address => uint128) usdValueTotalWithrawals;
```

\*see [ProtocolApplicationHandler](/v1/reference/client/application/ProtocolApplicationHandler.sol/contract.ProtocolApplicationHandler)

## Events

* **event AD1467\_ProtocolRuleCreated(bytes32 indexed ruleType, uint32 indexed ruleId, bytes32\[] extraTags)**:

  * Emitted when: the rule has been created in the protocol.
  * Parameters:
    * ruleType: "ACC\_MAX\_VALUE\_OUT\_ACCESS\_LEVEL".
    * ruleId: the index of the rule created in the protocol by rule type.
    * extraTags: empty array.

* **event AD1467\_ApplicationRuleApplied(bytes32 indexed ruleType, ActionTypes action, uint32 indexed ruleId);**:
  * Emitted when: rule has been applied in an application manager handler.
  * Parameters:
    * ruleType: "ACC\_MAX\_VALUE\_OUT\_ACCESS\_LEVEL".
    * action: the protocol action the rule is being applied to.
    * ruleId: the ruleId set for this rule in the handler.

* **event AD1467\_ApplicationRuleAppliedFull(bytes32 indexed ruleType, ActionTypes\[] actions, uint32\[] ruleIds);**:

  * Emitted when: rule has been applied in an application manager handler.
  * Parameters:
    * ruleType: "ACC\_MAX\_VALUE\_OUT\_ACCESS\_LEVEL".
    * actions: the protocol actions the rule is being applied to.
    * ruleIds: the ruleIds set for each action on this rule in the handler.

* **event AD1467\_ApplicationHandlerActivated(bytes32 indexed ruleType, ActionTypes action)**:
  * Emitted when: a rule has been activated in an application handler:
  * Parameters:
    * ruleType: "ACC\_MAX\_VALUE\_OUT\_ACCESS\_LEVEL".
    * action: the protocol action for which the rule is being activated.

## Dependencies

This rule depends on:

* **Pricing contracts**: [pricing contracts](/v1/pricing/overview) for ERC20s and ERC721s need to be set up in the token handlers in order for this rule to work.
