# Cash Modules

This contract is the main neobank financial operations module for EtherFi Vault users. User interactions with the EtherFi Cash system occur via the CashModule contract.

`CashModule` allows users to:

* Spend funds in Direct Pay mode or Credit mode
* Set spending limits
* Request and process withdrawals
* Earn cashback rewards
* Repay borrowed funds
* Switch between operational modes
* Configure cashback splits

CashModule is implemented as a set of contracts following the proxy pattern with distinct components:

* `CashModuleCore`: Core financial operations
* `CashModuleSetters`: Configuration management
* `CashModuleStorageContract`: Storage implementation
* `CashLens`: Read-only views

### Write Methods

#### setupModule

```solidity
function setupModule(bytes calldata data) external
```

Initializes the Cash Module for a new Vault.

Function is invoked when the Cash Module is added to an EtherFi Vault.

Sets up default spending limits and mode configuration.

**Input Parameters:**

| Name | Type  | Description                                                                                |
| ---- | ----- | ------------------------------------------------------------------------------------------ |
| data | bytes | The encoded initialization data containing daily limit, monthly limit, and timezone offset |

#### spend

```solidity
function spend(
    address vault,
    address spender,
    address referrer,
    bytes32 txId,
    BinSponsor binSponsor,
    address[] calldata tokens,
    uint256[] calldata amountsInUsd,
    bool shouldReceiveCashback
) external 

```

Processes a spending transaction, transferring funds from the Vault in either Direct Pay or Credit mode.

Requires the caller to have the `ETHER_FI_WALLET_ROLE`.

When spending in Direct Pay mode, tokens are transferred directly from the Vault to the settlement dispatcher. In Credit mode, tokens are borrowed against the Vault's collateral.

**Input Parameters:**

| Name                  | Type       | Description                                                             |
| --------------------- | ---------- | ----------------------------------------------------------------------- |
| vault                 | address    | The address of the EtherFi Vault                                        |
| spender               | address    | The address of the user initiating the spend                            |
| referrer              | address    | The address of the referrer (or address(0) if none)                     |
| txId                  | bytes32    | Unique transaction identifier                                           |
| binSponsor            | BinSponsor | Identifier of the bin sponsor (Rain or Reap)                            |
| tokens                | address\[] | Array of token addresses to spend                                       |
| amountsInUsd          | uint256\[] | Array of amounts in USD value to spend (must match tokens array length) |
| shouldReceiveCashback | bool       | Flag indicating if the transaction should earn cashback                 |

#### repay

```solidity
function repay(
    address vault,
    address token,
    uint256 amountInUsd
) public 

```

Repays borrowed tokens in Credit mode.

When repaying, the Vault must have sufficient balance of the token being used for repayment.

**Input Parameters:**

| Name        | Type    | Description                                 |
| ----------- | ------- | ------------------------------------------- |
| vault       | address | The address of the EtherFi Vault            |
| token       | address | The address of the token used for repayment |
| amountInUsd | uint256 | The amount to repay, expressed in USD value |

#### requestWithdrawal

```solidity
function requestWithdrawal(
    address vault,
    address[] calldata tokens,
    uint256[] calldata amounts,
    address recipient,
    address[] calldata signers,
    bytes[] calldata signatures
) external 

```

Requests a withdrawal of tokens from the Vault to a recipient address.

The function requires valid signatures from the Vault owners according to the Vault's threshold configuration.

Initiates a withdrawal request that will be available for processing after the withdrawal delay period.

**Input Parameters:**

| Name       | Type       | Description                                                       |
| ---------- | ---------- | ----------------------------------------------------------------- |
| vault      | address    | The address of the EtherFi Vault                                  |
| tokens     | address\[] | Array of token addresses to withdraw                              |
| amounts    | uint256\[] | Array of token amounts to withdraw                                |
| recipient  | address    | Address that will receive the tokens                              |
| signers    | address\[] | Array of Vault owner addresses that signed the withdrawal request |
| signatures | bytes\[]   | Array of signatures corresponding to the signers                  |

#### processWithdrawal

```solidity
function processWithdrawal(address vault) public 

```

Processes a pending withdrawal request after the delay period has passed.

The function executes the token transfers to the recipient specified in the withdrawal request.

Fails if the withdrawal delay period has not yet elapsed.

**Input Parameters:**

| Name  | Type    | Description                      |
| ----- | ------- | -------------------------------- |
| vault | address | The address of the EtherFi Vault |

#### setMode

```solidity
function setMode(
    address vault,
    Mode mode,
    address signer,
    bytes calldata signature
) external 

```

Sets the operational mode for a Vault (Direct Pay or Credit).

Switching to Credit mode may have a delay period depending on configuration. Switching to Direct Pay mode happens immediately after verification.

**Input Parameters:**

| Name      | Type    | Description                                            |
| --------- | ------- | ------------------------------------------------------ |
| vault     | address | The address of the EtherFi Vault                       |
| mode      | Mode    | The target mode (Direct Pay or Credit)                 |
| signer    | address | Address of the Vault admin signing the transaction     |
| signature | bytes   | Signature from the signer authorizing this mode change |

#### updateSpendingLimit

```solidity
function updateSpendingLimit(
    address vault,
    uint256 dailyLimitInUsd,
    uint256 monthlyLimitInUsd,
    address signer,
    bytes calldata signature
) external

```

Updates the spending limits for a Vault.

Changes to spending limits take effect after the configured delay period.

**Input Parameters:**

| Name              | Type    | Description                                        |
| ----------------- | ------- | -------------------------------------------------- |
| vault             | address | The address of the EtherFi Vault                   |
| dailyLimitInUsd   | uint256 | New daily spending limit in USD                    |
| monthlyLimitInUsd | uint256 | New monthly spending limit in USD                  |
| signer            | address | Address of the Vault admin signing the transaction |
| signature         | bytes   | Signature from the signer authorizing this update  |

#### setCashbackSplitToSafeBps

```solidity
function setCashbackSplitToSafeBps(
    address vault,
    uint256 splitInBps,
    address signer,
    bytes calldata signature
) external 

```

Sets the percentage of cashback that goes to the Vault (versus the spender).

The split is expressed in basis points, where 10000 represents 100%.

**Input Parameters:**

| Name       | Type    | Description                                         |
| ---------- | ------- | --------------------------------------------------- |
| vault      | address | The address of the EtherFi Vault                    |
| splitInBps | uint256 | Percentage in basis points to allocate to the Vault |
| signer     | address | Address of the Vault admin signing the transaction  |
| signature  | bytes   | Signature from the signer authorizing this change   |

#### clearPendingCashback

```solidity
function clearPendingCashback(address[] calldata users) external whenNotPaused

```

Clears pending cashback for a list of users.

Attempts to retrieve any pending cashback and distribute it to the specified users.

**Input Parameters:**

| Name  | Type       | Description                                           |
| ----- | ---------- | ----------------------------------------------------- |
| users | address\[] | Array of user addresses to clear pending cashback for |

### Read Methods

#### getMode

```solidity
function getMode(address vault) external view returns (Mode)

```

Gets the current operational mode of a Vault.

Considers pending mode changes that have passed their delay period.

**Input Parameters:**

| Name  | Type    | Description                      |
| ----- | ------- | -------------------------------- |
| vault | address | The address of the EtherFi Vault |

**Return Values:**

| Type | Description                                         |
| ---- | --------------------------------------------------- |
| Mode | The current operational mode (Direct Pay or Credit) |

#### canSpend

```solidity
function canSpend(
    address vault,
    bytes32 txId,
    address[] calldata tokens,
    uint256[] calldata amountsInUsd
) public view returns (bool, string memory)

```

Checks if a spending transaction can be executed.

Validates if the Vault has sufficient balance or borrowing power for the specified tokens and amounts.

**Input Parameters:**

| Name         | Type       | Description                       |
| ------------ | ---------- | --------------------------------- |
| vault        | address    | The address of the EtherFi Vault  |
| txId         | bytes32    | Transaction identifier            |
| tokens       | address\[] | Array of token addresses to spend |
| amountsInUsd | uint256\[] | Array of amounts in USD to spend  |

**Return Values:**

| Type   | Description                              |
| ------ | ---------------------------------------- |
| bool   | Whether the spending is allowed          |
| string | Error message if spending is not allowed |

#### maxCanSpend

```solidity
function maxCanSpend(
    address vault,
    address token
) public view returns (
    uint256 returnAmtInCreditModeUsd,
    uint256 returnAmtInDebitModeUsd,
    uint256 spendingLimitAllowance
)

```

Calculates the maximum amount that can be spent in both Credit and Direct Pay modes.

**Input Parameters:**

| Name  | Type    | Description                       |
| ----- | ------- | --------------------------------- |
| vault | address | The address of the EtherFi Vault  |
| token | address | The address of the token to spend |

**Return Values:**

| Type    | Description                                               |
| ------- | --------------------------------------------------------- |
| uint256 | Maximum amount that can be spent in Credit mode (USD)     |
| uint256 | Maximum amount that can be spent in Direct Pay mode (USD) |
| uint256 | Remaining spending limit allowance                        |

#### getSafeCashData

```solidity
function getSafeCashData(
    address vault
) external view returns (SafeCashData memory safeCashData)

```

Gets comprehensive cash data for a Vault.

Aggregates data from multiple sources including DebtManager and CashModule.

**Input Parameters:**

| Name  | Type    | Description                      |
| ----- | ------- | -------------------------------- |
| vault | address | The address of the EtherFi Vault |

**Return Values:**

| Type         | Description                                                                       |
| ------------ | --------------------------------------------------------------------------------- |
| SafeCashData | Comprehensive data structure containing mode, balances, borrowing power, and more |

#### getPendingCashback

```solidity
function getPendingCashback(address account) external view returns (uint256)

```

Gets the pending cashback amount for an account in USD.

**Input Parameters:**

| Name    | Type    | Description                               |
| ------- | ------- | ----------------------------------------- |
| account | address | Address of the account (Vault or spender) |

**Return Values:**

| Type    | Description                    |
| ------- | ------------------------------ |
| uint256 | Pending cashback amount in USD |

#### getData

```solidity
function getData(address vault) external view returns (SafeData memory)

```

Retrieves cash configuration data for a Vault.

**Input Parameters:**

| Name  | Type    | Description                  |
| ----- | ------- | ---------------------------- |
| vault | address | Address of the EtherFi Vault |

**Return Values:**

| Type     | Description                                        |
| -------- | -------------------------------------------------- |
| SafeData | Data structure containing Vault cash configuration |

### Events

The CashModule emits events for all major operations through the CashEventEmitter:

#### WithdrawalRequested

```solidity
event WithdrawalRequested(
    address indexed vault,
    address[] tokens,
    uint256[] amounts,
    address indexed recipient,
    uint256 finalizeTimestamp
)

```

Emitted when a withdrawal is requested.

#### WithdrawalProcessed

```solidity
event WithdrawalProcessed(
    address indexed vault,
    address[] tokens,
    uint256[] amounts,
    address indexed recipient
)

```

Emitted when a withdrawal is processed.

#### Spend

```solidity
event Spend(
    address indexed vault,
    bytes32 indexed txId,
    BinSponsor indexed binSponsor,
    address[] tokens,
    uint256[] amounts,
    uint256[] amountInUsd,
    uint256 totalUsdAmt,
    Mode mode
)

```

Emitted when tokens are spent from a Vault.

#### Cashback

```solidity
event Cashback(
    address indexed vault,
    address indexed spender,
    uint256 spendingInUsd,
    address cashbackToken,
    uint256 cashbackAmountToVault,
    uint256 cashbackInUsdToVault,
    uint256 cashbackAmountToSpender,
    uint256 cashbackInUsdToSpender,
    bool indexed paid
)

```

Emitted when cashback is calculated and potentially distributed.

#### ReferrerCashback

```solidity
event ReferrerCashback(
    address indexed vault,
    address indexed referrer,
    uint256 spendingInUsd,
    address cashbackToken,
    uint256 referrerCashbackAmt,
    uint256 referrerCashbackInUsd,
    bool indexed paid
)

```

Emitted when referral cashback is calculated and potentially distributed.

#### ModeSet

```solidity
event ModeSet(
    address indexed vault,
    Mode prevMode,
    Mode newMode,
    uint256 incomingModeStartTime
)

```

Emitted when the operational mode of a Vault is changed.

#### SpendingLimitChanged

```solidity
event SpendingLimitChanged(
    address indexed vault,
    SpendingLimit oldLimit,
    SpendingLimit newLimit
)

```

Emitted when a spending limit is changed.
