# Architecture

## Overview

This project features multiple market contracts centered around PredyPool. The market contracts define financial products and order types. Markets can leverage positions by utilizing PredyPool for token lending and borrowing. This architecture is highly scalable. For example, developers can create new futures exchanges with minimal code and gain leverage by connecting to PredyPool.

## Functional Diagram

<img src="https://2254474065-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fc0gVul8aBiXybg5yIkLr%2Fuploads%2FvMHCGmb4YxyL5L3plWu9%2Ffile.excalidraw.svg?alt=media&#x26;token=80bda9e9-8739-49c7-a312-cd9f96c75269" alt="" class="gitbook-drawing">

## Actors

### Operator/PoolCreator

Currently, the Operator and PoolCreator are the same and hold the admin role in the Predy protocol. Operator can register pairs and PoolCreator can update the parameters of registered pairs.

### **Lender**

A Lender is a user who provides tokens to Predy. These provided tokens are borrowed by traders when they open positions. Traders pay interest to the Lender, and in return, the Lender provides leverage to the traders.

### **Trader**

The Trader deposits margin and trades perps and [Squarts](https://docs.predy.finance/predy-v6/dev/squart). The Trader signs the order and passes the order and signature to the [Filler](#filler). The Filler is responsible for executing the actual transaction.

### Filler

The Filler is responsible for actually submitting and executing the Trader's orders on the blockchain. The Filler can determine the token exchange routes.

### **Liquidator**

When a trader's position meets the conditions for liquidation, the Liquidator forcibly closes the position. Liquidators can earn profits from the differences in the liquidation process.

### **Reallocator**

The Reallocator is responsible for reallocating the Uniswap V3 LP positions held by PredyPool to maintain [Squart](https://docs.predy.finance/predy-v6/dev/squart). Reallocation can be performed by anyone. The protocol does not incur any losses from the reallocation process.

## PredyPool

### RegisterPair

Register a pair of quoteToken and baseToken. In practice, register the corresponding Uniswap pool with the quoteToken. The token in the Uniswap pool that is not the quoteToken will become the baseToken.

For example, when specifying the address of USDC as the `quoteToken` and the ETH/USDC pool as the `uniswapPool`, the `baseToken` is automatically set to ETH, and a new pair is registered in Predy.

Let's look at the parameters in detail. We have already explained `quoteToken` and `uniswapPool`. `quoteIrmParams` and `baseIrmParams` define the interest rate curves for the deposited tokens. For specific usage, please refer to the [Interest Rate Model](https://docs.predy.finance/predy-v6/dev/interest-rate-model). poolOwner specifies the address that can update the pool's settings. `priceFeed` specifies [the contract](#pricefeed) that can obtain the oracle price for the pair. If a zero address is specified, the TWAP from the UniswapPool will be used as the oracle price. The `fee` indicates the percentage of the fee. it\`s the same as the [feeRatio](#updatefeeratio).  When `whitelistEnabled` is set to true, only specific addresses can trade in this pool. In `assetRiskParams`, risk parameters that determine the [Min. Value](https://docs.predy.finance/predy-v6/position-value#min.-margin) and the range size of Uniswap LP position are specified.

```solidity
struct AddPairParams {
    address quoteToken;
    address poolOwner;
    address uniswapPool;
    address priceFeed;
    bool whitelistEnabled;
    uint8 fee;
    Perp.AssetRiskParams assetRiskParams;
    InterestRateModel.IRMParams quoteIrmParams;
    InterestRateModel.IRMParams baseIrmParams;
}
```

### updateAssetRiskParams

Let's look at the parameters in detail. The `riskRatio` and `debtRiskRatio` are parameters used to calculate the minimum margin required to maintain a position. They correspond to $$r$$ and $$r\_{debt}$$ in [this equation.](https://docs.predy.finance/predy-v6/position-value#min.-margin) The `rangeSize` and `rebalanceThreshold` are explained in the [Reallocation section](#reallocation).&#x20;

The `minSlippage` and `maxSlippage` parameters define the slippage tolerance of the execution price from the oracle price during liquidation. The slippage tolerance is determined within the range of `minSlippage` and `maxSlippage`, based on the value of [vaultValue](https://docs.predy.finance/predy-v6/position-value#vault-value) / [minMargin](https://docs.predy.finance/predy-v6/position-value#min.-margin).

```solidity
struct AssetRiskParams {
    uint128 riskRatio;
    uint128 debtRiskRatio;
    int24 rangeSize;
    int24 rebalanceThreshold;
    uint64 minSlippage;
    uint64 maxSlippage;
}
```

### updateFeeRatio

The `feeRatio` indicates the percentage of the fee. For example, if the `feeRatio` is 10%, 10% of the borrowing interest is collected as a fee. Half of this, 5%, goes to the protocol, and the other half, 5%, goes to the pool creator.&#x20;

### Supply

It is a function to provide either the quoteToken or the baseToken to the lending pool. In return, the lender receives bond tokens.

### Withdraw

It is a function to withdraw either the quoteToken or the baseToken from the lending pool. In return, the lender burns the bond tokens.

### Trade

It is a function to trade perp and [Squart](https://docs.predy.finance/predy-v6/dev/squart) using quoteToken as collateral. It is intended to be called by the [market contract](#market-contracts).

```solidity
function trade(TradeParams memory tradeParams, bytes memory settlementData)
    external
    returns (TradeResult memory tradeResult);

```

In `tradeParams`, specify `pairId`, `vaultId`, and the amounts of perp and Squart. If `vaultId` is 0, a new vault is created. `settlementData` is passed directly to `predySettlementCallback`, and `extraData` will be used in`predyTradeAfterCallback`.

```solidity
struct TradeParams {
    uint256 pairId;
    uint256 vaultId;
    int256 tradeAmount;
    int256 tradeAmountSqrt;
    bytes extraData;
}

```

### Liquidation

If the [Vault Value](https://docs.predy.finance/predy-v6/position-value#vault-value) becomes smaller than the Min. Margin, the vault can be forcefully closed. The liquidation price is determined through a Dutch auction, based on the ratio of Vault Value to Min Margin.

#### Calculating Slippage Tolerance

The value of `slippageTolerance` is determined by the ratio of `vaultValue` to `minMargin`. The smaller the vaultValue/minMargin ratio, the larger the `slippageTolerance`. As `slippageTolerance` increases, the difference between the market price and the liquidation price also grows, thereby providing a greater incentive for the liquidator. <https://github.com/predyprotocol/predyx/blob/main/src/libraries/logic/LiquidationLogic.sol#L159>

### Reallocation

The `Reallocate` function repositions the LP (Liquidity Provider) funds within the specified range as described in Squart. This function can be called by anyone.

This section explains how to allocate the LP range effectively. The relevant parameters for this process are `rangeSize` and `rebalanceThreshold`.

* `rangeSize` specifies the width of the LP range.
* `rebalanceThreshold` specifies the threshold at which reallocation occurs.

For example, if the current tick of the UniswapPool is 100, the `rangeSize` is 200, and the `rebalanceThreshold` is 100, the initial range is (-100, 300), and the reallocation threshold is set at (0, 200). If the tick exceeds 200, the LP position is reallocated around the current tick. If the tick becomes 210, the new range will be (10, 410).

For specific reallocation methods, please refer to [Squart](https://docs.predy.finance/predy-v6/dev/squart) and [the activity flow](https://docs.predy.finance/predy-v6/dev/flowchart#reallocate).

### Take

The `take` function is explained [here](#interact-with-the-pool-and-manage-funds).

## Market Contracts

The MarketContract defines the specifics of a market. For example, it implements an intent-based approach (signature verification with permit2, swaps on Uniswap, delta hedging, etc.). The MarketContract needs to have the following functions:

* predySettlementCallback: defines the method for exchanging tokens.
* predyTradeAfterCallback: defines the method for adding collateral.

```solidity
interface IHooks {
    function predySettlementCallback(
        address quoteToken,
        address baseToken,
        bytes memory settlementData,
        int256 baseAmountDelta
    ) external;

    function predyTradeAfterCallback(
        IPredyPool.TradeParams memory tradeParams,
        IPredyPool.TradeResult memory tradeResult
    ) external;

```

### Interact with the pool and manage funds

Within the callback, the MarketContract can call the `take` function of the PredyPool. The `take` function allows any amount of tokens to be sent from the PredyPool to any destination. After the callback finishes, the PredyPool verifies that there are no issues with the token amount difference.

Specifically, in the case of `predySettlementCallback`, the difference in quoteToken is reflected in the entryValue (i.e., the entry price). In the case of `predyTradeAfterCallback`, the difference in quoteToken is reflected in the collateral. The system then checks the safety of the vault and verifies that there are no issues with the trade.

### Example Sequence of a Trade

<figure><img src="https://2254474065-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fc0gVul8aBiXybg5yIkLr%2Fuploads%2FHNzbGm5a1BflMgeHUr5u%2FScreenshot%202024-05-20%20at%2017.44.52.png?alt=media&#x26;token=0cda1998-8bba-4558-b72d-75b41a4f366e" alt=""><figcaption><p>The process of shorting 1 WETH with a collateral of 100 USDC</p></figcaption></figure>

## PriceFeedFactory

PriceFeedFactory is the factory contract for the PriceFeed contract. The PriceFeed contract can be used as the `priceFeed` parameter when registering a pair. In `quotePrice`, specify the Chainlink address corresponding to the USD-denominated price of the `quoteToken`. In `priceId`, specify the Pyth address corresponding to the USD-denominated price of the `baseToken`. The `decimalsDiff` parameter adjusts the decimal places. As a return value, the address of the PriceFeed contract is returned.

```solidity
function createPriceFeed(
　　address quotePrice,
　　bytes32 priceId,
　　uint256 decimalsDiff
) external returns (address)
```

## PriceFeed

### getSqrtPrice

It returns the square root value of the baseToken price denominated in quoteToken. Similar to Uniswap's sqrtPriceX96, the value is scaled by 2^96.
