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

# Current Architecture

## Contract overview

**FlashLeverage**\
The main contract users interact with. Handles the full position lifecycle: opening, adjusting, and closing. Also manages fees, LTV validation, UserProxy creation, market configuration, and admin controls. Inherits MarketPositionManager, SwapManager, ReentrancyGuard, and Ownable2Step.

**MarketPositionManager**\
Abstract base for all Morpho protocol interactions. Houses the flash loan callback handler (`onMorphoFlashLoan`), collateral supply and withdrawal, borrow and repay logic, position queries, share-to-asset conversion, and market parameter storage. FlashLeverage inherits from this.

**SwapManager**\
Handles token swaps through whitelisted external aggregators. No internal AMM. Delegates to routers like KyberSwap, Odos, or Pendle Router using encoded calldata. Validates router approval and verifies output meets `minTokenOut` before completing any swap.

**UserProxy**\
An EIP-1167 minimal clone deployed per position. Holds the position's Morpho collateral and debt in isolation. During normal operation, only FlashLeverage can call it. Manual Mode unlocks direct access for the position owner. Includes a `recover()` function for tokens accidentally sent to the proxy or accumulated as external rewards.

**FlashLeverageRouter**\
Entry point for users who do not hold the collateral token. Combines a token swap and a `leverage()` call into one transaction. Also integrates with Morpho Public Allocator for vault liquidity reallocation before opening a position.

***

## Inheritance

```text theme={null}
FlashLeverage
├── MarketPositionManager
│   └── SwapManager
├── ReentrancyGuard (OpenZeppelin)
└── Ownable2Step (OpenZeppelin)
```

***

## Key structs

**LeveragePosition** — stored per user per position ID

* `open`: bool
* `marketId`: Id
* `userProxy`: address
* `amountDepositedInLoanToken`: uint256, tracks cumulative deposits for yield fee calculation
* `amountReturnedInLoanToken`: uint256

**LeverageParams** — input for `leverage()`

* `marketId`, `amountCollateral`, `amountFlashLoan`, `swapData`, `minTokenOut`

**MarketConfig**

* `marketId`: Id
* `isCorrelated`: bool

**SwapData**

* `extRouter`: address
* `extCalldata`: bytes

***

## Key functions

`leverage(user, params)`\
Opens a new position. Takes a `user` address, so anyone can open a position on behalf of another. Transfers collateral in, deploys a UserProxy for the position, flash-loans the borrow amount, swaps to additional collateral, supplies the total to Morpho, and borrows to repay the flash loan. Deposit fee applied here for non-correlated markets.

`deleverage(positionId, amountCollateral, swapData, minTokenOut)`\
Closes a position. Position owner only. Flash-loans the full outstanding debt, repays Morpho, withdraws collateral, swaps to loan token, deducts yield fee on profit for correlated markets, and returns the remainder to the caller.

`increaseLeverage(positionId, amountFlashLoan, swapData, minTokenOut)`\
Amplifies an existing position. Position owner only. Flash-loans additional funds, swaps to collateral, supplies the additional collateral, and borrows to repay.

`supplyCollateral(user, positionId, amountCollateral)`\
Adds collateral to reduce LTV. Callable by anyone for any position. Deposit fee applies for non-correlated markets. Updates `amountDepositedInLoanToken` for accurate fee accounting.

`repay(user, positionId, amountRepay, borrowShares)`\
Repays debt on a position. Callable by anyone. Deposit fee applies for non-correlated markets.

`borrow(positionId, amountBorrow)`\
Extracts loan tokens from an existing position. Position owner only. Non-correlated markets only. Blocked on correlated pairs to preserve yield accounting integrity.

`withdrawCollateral(positionId, amountWithdraw)`\
Removes collateral from a position. Position owner only. LTV is validated after withdrawal. Yield fee applies on correlated markets if profit is realized.

`enableManualMode(userProxy)`\
Owner only. Unlocks a specific UserProxy so the position owner can interact with Morpho directly. Used for emergency recovery upon user request.

***

## Flash loan callback

All flash loan operations funnel into a single `onMorphoFlashLoan(uint256 amountLoan, bytes calldata data)` callback. The `data` payload encodes an `Action` enum (LEVERAGE or UNLEVERAGE) that routes execution to `_handleLeverage()` or `_handleDeleverage()` in MarketPositionManager. The callback validates `msg.sender == address(i_morpho)` before executing any logic.

***

## Constants

| Constant            | Value | Description                                                    |
| :------------------ | :---- | :------------------------------------------------------------- |
| LIQUIDATION\_BUFFER | 0.25% | Subtracted from market LLTV to set max allowed LTV. Immutable. |
| MAX\_YIELD\_FEE     | 10%   | Hard cap on yield fee. Immutable.                              |
| MAX\_DEPOSIT\_FEE   | 1%    | Hard cap on deposit fee. Immutable.                            |

If a Morpho market has a liquidation LTV of 90%, the protocol caps positions at 89.75% LTV.

<Note>
  `s_yieldFee` and `s_depositFee` are both initialized to 0 in the constructor and are 0 on every live deployment. The fee paths described above are present in the code but currently deduct nothing — the only fee the protocol charges is the 10 bps swap fee at entry. See [Fees](/fees).
</Note>

***

## Libraries

**Math.sol** — Fixed-point arithmetic at 18-decimal precision. Used for fee and LTV calculations throughout.

**TokenHelper.sol** — Safe ERC20 transfer utilities. Uses `address(0)` as the convention for native ETH.

**Error.sol** — Custom error definitions for all revert conditions across the protocol.
