# Introduction to Perennial

### Derivatives Redesigned for DeFi

<figure><img src="/files/JOKdGfB6U5iyUiDVSpVF" alt=""><figcaption></figcaption></figure>

**A Full-Stack Perps Ecosystem**

Perennial is a **layered ecosystem**, enabling the most capital-efficient and seamless perps trading experience.

1️⃣ **The Protocol Layer** → A perps primitive designed for seamless leveraged exposure. Traders take positions, while makers & LPs manage risk with full flexibility. Powered by a hybrid intent-AMM model, it facilitates three-sided markets, settling trades against an oracle price feed.

2️⃣ **The Rollup Layer** → A dedicated perps rollup on Base, optimizing for near-zero fees, scalable throughput, and fast execution—ensuring the smoothest trading experience.

3️⃣ **The Product Layer** → Multiple frontends leverage Perennial’s protocol, including app.perennial.finance for pro traders, perp.fun for retail, and third-party integrations such as Slingshot (soon).

### **How does it work?**

The Perennial protocol is a **settlement layer** for market-isolated derivatives trades. **Takers (traders)** can submit offchain (Intent) or onchain (AMM) orders to gain exposure to a market's underlying oracle price. Regardless of order type, positions are settled into the market’s **peer-to-pool** derivatives AMM, with funding & interest rates adjusting dynamically based on market skew & utilization.

**Takers (Traders)** deposit collateral & open a position to gain leveraged exposure to price feeds—long, short, or exotic payoffs. With **Intent orders**, a **Taker’s** position is matched with an opposing order from a **Maker** before being settled into the AMM. For AMM orders, **Takers** are directly netted against each other within the market.

Where a shortfall exists between **Takers**, **Liquidity Providers (LPs)** step in to fill the gap—earning fees while managing exposure. LPs take on risk proportional to the imbalance between longs and shorts. **On an ongoing basis, takers & LPs settle up; the losing side pays the winning side.**

### Why Perennial?

At its core, Perennial is a **minimalist, DeFi-native primitive**, providing the foundational infrastructure for derivative markets while allowing **developers, traders, and liquidity providers** to interact at any level.

Some things that make the Perennial protocol stand out:

* **Hybrid Intent-AMM** — A next-gen model combining offchain intent matching with onchain AMM settlement for deep liquidity & optimized execution.
* **Cash-settled** — Trades are settled in $USD, aligning with the most popular crypto derivatives.
* **Low fees** — A hyper-efficient design minimizes costs for both takers & makers.
* **Native LP Leverage** — LPs can provide capital at significant leverage (up to 50x) and can fully customize their risk exposure & hedging strategy (or lack thereof).
* **Built for the needs of Developers** — A composable, fully on-chain primitive designed for easy integration and expansion.
* **Permissionless** — Open market creation, integration, and composability.

To dive deeper, see the [Mechanism](https://www.notion.so/o/L4EUNHdWsBUAEDZqMBNt/s/esXIGSYvKcOjqMTCdsjo/~/changes/53/protocol/~/overview) section, or explore the layers of Perennial below.

### Dive in

<table data-view="cards" data-full-width="false"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center">Markets</td><td><a href="/pages/WubA4KDiB52lM7iKPYjo">/pages/WubA4KDiB52lM7iKPYjo</a></td></tr><tr><td align="center">Intents</td><td><a href="/pages/FNcM172EM9GCpC7P7HCx">/pages/FNcM172EM9GCpC7P7HCx</a></td></tr><tr><td align="center">Vaults</td><td><a href="/pages/SB9DbdF6uvUsFQdGpPN0">/pages/SB9DbdF6uvUsFQdGpPN0</a></td></tr><tr><td align="center">Integrating Perennial</td><td><a href="/pages/DrRtEvbdXCHfheptWCIB">/pages/DrRtEvbdXCHfheptWCIB</a></td></tr><tr><td align="center">Live Contracts</td><td><a href="/pages/X5Cb9FpZY7jalA7NzXzL">/pages/X5Cb9FpZY7jalA7NzXzL</a></td></tr><tr><td align="center">Audits &#x26; Bug Bounty</td><td><a href="/pages/9EaeMAC5S8WbpqGb0a0C">/pages/9EaeMAC5S8WbpqGb0a0C</a></td></tr></tbody></table>

### Get in touch

<table data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center">Website</td><td><a href="https://perennial.finance/">https://perennial.finance/</a></td></tr><tr><td align="center">Github</td><td><a href="https://github.com/equilibria-xyz/perennial-mono">https://github.com/equilibria-xyz/perennial-mono</a></td></tr><tr><td align="center">Twitter</td><td><a href="https://twitter.com/perenniallabs">https://twitter.com/perenniallabs</a></td></tr><tr><td align="center">Discord</td><td><a href="https://discord.gg/n6ejatX5Rw">https://discord.gg/n6ejatX5Rw</a></td></tr><tr><td align="center">Medium</td><td><a href="https://medium.com/perennial-protocol">https://medium.com/perennial-protocol</a></td></tr></tbody></table>


# Perennial Petals

<figure><img src="/files/bxsU2B6qFM3zAS4RBI3b" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Season 1:** Dec 3rd ➡ Feb 17th\
**Season 2:** Feb 25th ➡ \[redacted]
{% endhint %}

Perennial is committed to creating a hyper-efficient DeFi landscape for perpetuals, and in doing so we aim to recognize the community who help drive this mission.

The **Petals Program** is a long-term initiative that rewards early adopters, loyal participants, and newcomers alike.

A total of **1,250,000 petals are distributed weekly**.

{% hint style="info" %}
During Week 1 of Season 1 — 2,500,000 petals were distributed thanks to the 2x boost week.
{% endhint %}

### **Earning Petals: A Quick Guide**

There are multiple ways to earn Petals in the program:

* **Trading on Perennial**: Every trade on [app.perennial.finance](http://app.perennial.finance) earns you Petals.
* **Retroactive Petal Distribution (coming soon):** Loyal users of Perennial will be rewarded for their past trading and LP activity.
* **Participating on Partner Platforms**: Every trade on other Perennial-powered frontends earns you Petals. These must be through Perennial-powered markets specifically.

Additionally, you can earn via **Petal Quests,** which are community challenges to help grow the Perennial ecosystem and earn rewards.

#### **Tracking Your Petals**

Keeping track of your Petals is simple. Just connect your wallet on the **Petals tab** within the Perennial platform. This page displays all your earned Petals, plus any active rewards or boosts.

#### **Why Earn Petals?**

Earning Petals isn’t just about rewards—it’s a way to represent your involvement in Perennial’s journey and growth. As you accumulate Petals, your engagement with the Perennial protocol reflects your standing and contribution within the ecosystem.

### **Referrals**

Users can earn a **25% points match** for each new trader they bring to the platform. Simply generate a unique referral code on the [**Refer**](https://app.perennial.finance/referrals) page and share it. New users will enter your code on the [**Refer**](https://app.perennial.finance/referrals) page when they join, linking their activity to your referral rewards.

***

#### Legal Notice

By participating in the Rewards Program, you accept and agree to be bound and comply with the **Terms**. All capitalized terms used in this Notice will have the meanings set forth in the **Terms**.

Rewards are not, and may never convert to, accrue to, be used as a basis to calculate, or become, any tokens or other digital assets offered or promoted by us. Rewards do not constitute any currency or property of any type. You acknowledge that we are under no obligation to generate tokens.

Rewards are strictly non-transferable, and you may not attempt to sell, trade, or transfer any Rewards, or obtain any manner of credit using any Rewards. Any attempt to sell, trade, or transfer any Rewards will be null and void, except as we may explicitly state otherwise in a written update to this notice on the Interface.

We reserve the right to cancel, change, discontinue, limit, modify, or withdraw the Rewards Program (including the frequency, criteria, calculation and eligibility for earning such Rewards), at any time with or without notice and regardless of any particular accumulation of Rewards.

You agree not to engage in any manipulative, fraudulent, dishonest, or abusive activities in connection with Rewards or any distribution of digital assets by us or our affiliates. This includes, but is not limited to, creating multiple accounts to claim additional Rewards, using bots or scripts to automate claiming, or participating in any schemes that artificially inflate the number or perceived value of Rewards, including but not limited to wash trading. We or our affiliates may terminate any or all of your Rewards due to such activities, or for breaching any license granted by us, and may disclose privately and publicly why such action was taken.

Staking of Rewards is strictly prohibited.

Rewards are not available to US Persons or Restricted Persons.


# Trading Competition - Flight School

### **Welcome to Flight School – The Trading Competition**

A new trading competition from perp.fun. Two consecutive 1-week battles to prove your skills and earn your spot on the first Autopilot leaderboard among the best.

**At stake:** cash prizes and a coveted place on the Autopilot leaderboard at launch — where you’ll earn 10% of the profits from everyone copying your trades.

***

### **Competition Details**

📆 Duration:\
**Comp 1:** March 31st, 2025 — April 7th, 2025\
**Comp 2:** April 7th, 2025 — April 14th, 2025

💰 Total Prizes (each week):\
$2,500 USDC + Autopilot leaderboard spot

***

### **Format & Prizes**

**Top PnL% (Top 2 Traders)**\
Traders will be ranked by highest PnL% during the competition.

**Prizes per week:**\
🥇 1st Place → $2,000 USDC + Autopilot leaderboard spot\
🥈 2nd Place → $500 USDC

***

### **Eligibility**

* **$25,000 minimum notional volume** traded during the competition

***

### **How to Participate**

* Trade on [perp.fun](https://perp.fun) during the comp window
* Meet the eligibility criteria
* Keep your positions strong — the highest PnL% wins

***

Winners will be announced after each competition ends.

**Autopilot awaits.**


# Rebates and Rewards

## Referrers: Earn USDC Rewards

Perennial’s referral program is open, meaning everyone (trader, community member, influencer, LP) is able to create referral codes & earn rewards.

To create and manage your referral code:

* On **Perennial**, head to the **"Refer"** tab in the app to generate and enter your code.
* On **Perpfun**, open the menu and use the **Refer Widget** to enter and share your referral code.

You’ll earn a percentage of all trading fees generated by users who enter your code. The more volume your referrals trade, the more you earn. Rewards are tracked on a 14-day rolling window and paid weekly in USDC.

Your referral tier updates automatically as volume increases. There is no cap on earnings.

***

## **Traders: Fee Rebates**

Traders receive automatic fee discounts based on their own trading activity and the referral link they used.

* **Higher personal volume → higher fee rebate (paid back to you weekly).**
* **Higher referrer tier → bigger upfront fee discount when you trade.**

Every trade you make counts toward your **14-day rolling volume**. As you trade more, you unlock higher tiers and get bigger discounts. The rebate is automatically tracked on all trades, and claimable weekly in-app.

If your referrer has a high volume tier, you benefit even more. Their rebate tier stacks with your own, reducing your trading fees further.

You can check your current tier and referral status from your profile page on either **Perennial** or **Perpfun**.

***

## 🧩 Referral Tiers

Referral rewards on Perennial are volume-based. Both traders and referrers move up tiers based on their **14-day rolling volume**.

As your volume increases, so do your rewards.

**Tier Breakdown**

<table><thead><tr><th>Tier</th><th width="149.5078125">14-Day Volume</th><th width="175.98046875">Rewards for Referrers</th><th width="302.1953125">Rebates for Traders (Trader / Referrer Vol)</th></tr></thead><tbody><tr><td>None</td><td>&#x3C; $50,000</td><td>0%</td><td>0% / 0%</td></tr><tr><td>Silver</td><td>≥ $50,000</td><td>10%</td><td>10% / 10%</td></tr><tr><td>Gold</td><td>≥ $500,000</td><td>15%</td><td>15% / 15%</td></tr><tr><td>Platinum</td><td>≥ $5,000,000</td><td>20%</td><td>20% / 20%</td></tr><tr><td>Solaris</td><td>≥ $50,000,000</td><td>25%</td><td>25% / 25%</td></tr></tbody></table>

Discounts are applied as **rebates**, credited weekly based on your 14-day trading volume.

Your referrer earns **rewards** too - based on *their* 14-day volume.

All rewards are calculated weekly and claimable in-app.

#### 💡 Example:

* If your 14-day volume is $600K (Gold), and your referrer’s is $5.2M (Platinum):
* You’ll get back 35% (15% for your volume, 20% for your referrer's) of your trade fees as a rebate
* Your referrer earns 20% of your trade fees as a reward

***

## Reward Calculation & Claiming

Rebates and rewards are calculated weekly based on a 14-day rolling trading volume.

* **Rebates** go to both the trader and their referrer
* **Volume Tiers** are based on your 14-day trailing volume
* **Calculations** are based on total notional traded and your current tier

Rewards are denominated in USDC and are claimable directly in the app.

💡 **How it works:**

1. You trade → full fee is charged up front (4.0 bps)
2. System calculates your & your referrers tier
3. Your share of that fee is returned to you as a **rebate**
4. Your referrer also gets a cut as their **referral reward**
5. You can claim your rewards weekly via the **refer tab**

💡 **Example calculation:**

* You trade $1M notional
* Your tier = 15%, your referrer’s = 20%
* Base fee = 4.0 bps = $400
* You get back $140 (15% + 20%)
* Your referrer gets $80 (20%)


# Mainnet

## **Chain Information**

**Chain ID:** `1424`

**Explorer:** <https://explorer.perennial.foundation>

**Public RPC:** <https://rpc.perennial.foundation>

**Subgraph**: <https://api.perennial.foundation/subgraphs/perennial>

**Settlement**: Base

**Data Availability**: Celestia

## Bridges

> List of all bridges: <https://bridges.perennial.foundation/>

### Native Bridge

**Origin Chain:** Base

**Contract (Base ETH & ERC20 ):** [0xA4a79672630054f2B6610966eA44556218866b02](https://basescan.org/address/0xA4a79672630054f2B6610966eA44556218866b02)

**Contract (Base USDC):** [0xcD1BB859294C232A7A3f90672DB2538079DDBA77](https://basescan.org/address/0xcD1BB859294C232A7A3f90672DB2538079DDBA77)

> *<mark style="background-color:blue;">This contract is only for Bridged USDC as Perennial supports the</mark>* [*<mark style="background-color:blue;">Bridged USDC Standard</mark>*](https://www.circle.com/bridged-usdc)*<mark style="background-color:blue;">.</mark>*

**Website:**  <https://bridge.perennial.foundation/>

### Fast Bridge - Relay

**Origin Chain:** Most EVM & SVM chains

**Website:** [Relay.link](https://www.relay.link/bridge/base?includeChainIds=8262e08d-57c9-4b4f-8dfe-6c92ee79354e\&fromChainId=1424\&fromCurrency=0x39cd9ef9e511ec008247ad5da01245d84a9521be\&toCurrency=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913)

### Fast Bridge - Decent.xyz

**Origin Chain:** Most EVM chains

**Website:** [Decent.xyz](https://app.decent.xyz/?srcToken=8453:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\&dstToken=1424:0x39cd9ef9e511ec008247ad5da01245d84a9521be)

## **Protocol Contracts:**

<table><thead><tr><th width="275">Contract</th><th>Address</th></tr></thead><tbody><tr><td>AccountImpl</td><td>0x298e0B0a38fF8B99bf1a3b697B0efB2195cfE47D</td></tr><tr><td>AccountVerifier</td><td>0xB5585A0cAac9f384A6Db545e89d0AC58215DBeFb</td></tr><tr><td>AccountVerifierImpl</td><td>0xe5cdb8345Bb38cb451FCbA14377A0c7F181a91ec</td></tr><tr><td>CheckpointLib</td><td>0x560276178203095afe2b055eB06e4E9eAF4CE0b1</td></tr><tr><td>CheckpointStorageLib</td><td>0x2b99224DAD73d7D84b7C74E9161BbD0D01a2A15b</td></tr><tr><td>Controller</td><td>0xe69FdDc2c8aDA6BE0ed02aE414f138B8edBC1D1c</td></tr><tr><td>ControllerImpl</td><td>0x83C69F035dB26BAED4E557A757Cc0C06F400DB37</td></tr><tr><td>GlobalStorageLib</td><td>0xe72E82b672d7D3e206327C0762E9805fbFCBCa92</td></tr><tr><td>GuaranteeStorageGlobalLib</td><td>0xe8eE3b7d74BD6eEBbA0992353b9fEC66ABF28DC8</td></tr><tr><td>GuaranteeStorageLocalLib</td><td>0x41b32C53D4e504BF39a0a080d0F7e3908108e4E1</td></tr><tr><td>InvariantLib</td><td>0xc6D91b171bAb98A458908EBDB5329B6bBD461Cd7</td></tr><tr><td>Inverse</td><td>0xC12b0fE62441bAAd525cd7d770cf21C883C77bc6</td></tr><tr><td>KeeperOracleImpl</td><td>0x6cF1A4373ba7D10bC37fAeC4694807B626B7f161</td></tr><tr><td>MagicValueLib</td><td>0xE547a6D15e5d28437dd1fEF67a3545adE6c53aA3</td></tr><tr><td>MakerVaultFactory</td><td>0xAEf566ca7E84d1E736f999765a804687f39D9094</td></tr><tr><td>MakerVaultFactoryImpl</td><td>0x4AA8B447417815807b955757a6D1b78b86f3aD22</td></tr><tr><td>MakerVaultImpl</td><td>0x9d2CaE012AAe0aE00f4d8F42CD287a6923612456</td></tr><tr><td>Manager</td><td>0x2C19eac953048801FfE1358D109A1Ac2aF7930fD</td></tr><tr><td>ManagerImpl</td><td>0x17aBb7df4cdCddA78039D51Abacfd2B75f82434f</td></tr><tr><td>MarketFactory</td><td>0xC27399bE9E39f7F6b1f94fBd512F5c2aD2b5eDb7</td></tr><tr><td>MarketFactoryImpl</td><td>0x18D1e8c75D7D3b91307bC08D85eb746A418DD2D3</td></tr><tr><td>MarketImpl</td><td>0x26F70E5fA46aD10DF9d43ba469cfAbC79B073a01</td></tr><tr><td>MarketParameterStorageLib</td><td>0x19890Cf5C9A0B8d2F71eB71347d126b6F7d78B76</td></tr><tr><td>MultiInvoker</td><td>0xB3DC5187B1Fb6F1b41852cFeBE06d370384110eF</td></tr><tr><td>MultiInvokerImpl</td><td>0x5d3A779CEa67947927bF78c61473778c46A97236</td></tr><tr><td>OracleFactory</td><td>0x49bCb3e1b0bA6A68EE1f1941EB56Ac7F46B67e09</td></tr><tr><td>OracleFactoryImpl</td><td>0xf3E6057474199179D9eFb733f2cf47F41Cc8a1ED</td></tr><tr><td>OracleImpl</td><td>0xA59eF0208418559770a48D7ae4f260A28763167B</td></tr><tr><td>OrderStorageGlobalLib</td><td>0x5A572B5fBBC43387B5eF8de2C4728A4108ef24a6</td></tr><tr><td>OrderStorageLocalLib</td><td>0xC5e9Ef91DC7E1D99bd44F9690FF0B982cAf846B9</td></tr><tr><td>OrderVerifier</td><td>0x32F3aB7b3c5BBa0738b72FdB83FcE6bb1a1a943c</td></tr><tr><td>OrderVerifierImpl</td><td>0x0A8c471070623579D07E57F3B4E058999855E598</td></tr><tr><td>PositionStorageGlobalLib</td><td>0xE77076D3EeE12dA1d7402Ff4e6Ca12A8d99FcE8B</td></tr><tr><td>PositionStorageLocalLib</td><td>0xdc518208c11159844188f647413a427Cbd70a3b6</td></tr><tr><td>PowerHalf</td><td>0x4a0f50b19b02AC927911C559629536B9a24d9314</td></tr><tr><td>PowerTwo</td><td>0x4f75cFbfc8b4A109659471b8d4593f5b19Be169B</td></tr><tr><td>ProxyAdmin</td><td>0x16b38364bA6f55B6E150cC7f52D22E89643f3535</td></tr><tr><td>RiskParameterStorageLib</td><td>0xa5492624F46F7ef346BfC46A0fB364eBa3b1f525</td></tr><tr><td>SolverVaultFactory</td><td>0x6a16E496e2fe24FD191b7Fe676dA481fC1a9e174</td></tr><tr><td>SolverVaultFactoryImpl</td><td>0x92F8d5B8d0ca2fc699c7c540471Ad49724a68007</td></tr><tr><td>SolverVaultImpl</td><td>0x7110eB89Da566f098BbeaB7471a61c22FCf5397C</td></tr><tr><td>StorkFactory</td><td>0xfFE829F928Cb8C07961bfFF04512ac0749d65d27</td></tr><tr><td>StorkFactoryImpl</td><td>0xa70eb2DBE380467175d7D793B0875887ABB2D660</td></tr><tr><td>Stork_CommitmentGasOracle</td><td>0x38934b335543246A49F82dbf364C37BbC877d9f2</td></tr><tr><td>Stork_SettlementGasOracle</td><td>0x0818E46C726810c2f7a1C513D0637a862bc0df6F</td></tr><tr><td>TimelockController</td><td>0xA8b58125953c7f2948E82A4558C745C1Cd3237ee</td></tr><tr><td>Verifier</td><td>0xfC20BccA96BDE758E9C69151d99cEcfEAE3AB37E</td></tr><tr><td>VerifierImpl</td><td>0xAF8CeD28FcE00ABD30463D55dA81156AA5aEEEc2</td></tr><tr><td>VersionLib</td><td>0x1593318424df66128cb7d0c5574B1283C3A74C3d</td></tr><tr><td>VersionStorageLib</td><td>0x8b3BaEaee9FB366A01AE73f87F2cc1BbAb54dFC8</td></tr></tbody></table>

## **External Contracts:**

<table><thead><tr><th width="252">Contract</th><th>Address</th></tr></thead><tbody><tr><td>USDC</td><td><a href="https://explorer.perennial.foundation/address/0x39CD9EF9E511ec008247aD5DA01245D84a9521be?tab=contract">0x39CD9EF9E511ec008247aD5DA01245D84a9521be</a></td></tr><tr><td>Stork (Oracle)</td><td><a href="https://explorer.perennial.foundation/address/0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62">0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62</a></td></tr><tr><td></td><td></td></tr></tbody></table>


# Testnet

## Chain Info

**Chain ID:** `60850`

**Explorer:** <https://explorer-sepolia.perennial.foundation>

**Public RPC:** <https://rpc-sepolia.perennial.foundation>

**Subgraph:** <https://api.perennial.foundation/subgraphs/perennial-sepolia>

**Settlement:** Base Sepolia

**Data Availability:** Celestia

## Bridges

### Native Bridge

**Origin Chain:** Base Sepolia

**Contract (Base Sepolia):** [0x0B2e528fd0181a20906a429a8bDb7c9bD6348b52](https://sepolia.basescan.org/address/0x0B2e528fd0181a20906a429a8bDb7c9bD6348b52)

**Website:** TBC

## Protocol Contracts

<table><thead><tr><th width="282">Contract</th><th>Address</th></tr></thead><tbody><tr><td>AccountImpl</td><td>0x443cef645e29aE12C053f358b2875DF0B9A43166</td></tr><tr><td>AccountVerifier</td><td>0x1cc0E7883DC01cCa0CC7A04b1Eb3e51C290645E7</td></tr><tr><td>AccountVerifierImpl</td><td>0x781bbEdDafe58e3934F0463294b7681d74ba1847</td></tr><tr><td>CheckpointLib</td><td>0xf2240d873E9174F2a7B0c816109908812A8e47e0</td></tr><tr><td>CheckpointStorageLib</td><td>0xC233A4d46052f4927f2d60aefAC6aBb51bb5A2E0</td></tr><tr><td>Controller</td><td>0x07B891ae5E0eeAF7FB407552C28EAc785Ac8AF9C</td></tr><tr><td>ControllerImpl</td><td>0x3B778B8f92aA501de6f1f73F6CfF32322dBfA0dF</td></tr><tr><td>GlobalStorageLib</td><td>0xFB17EB91262c4d4ef81C5f00A216Cf4F31556a22</td></tr><tr><td>GuaranteeStorageGlobalLib</td><td>0xDE7E2d1005Ea46a0e261E243F762Fc7Ca849ACAB</td></tr><tr><td>GuaranteeStorageLocalLib</td><td>0xfEeFDbcCfabF023A6a9F0fa0b67aEE80A861c7ed</td></tr><tr><td>InvariantLib</td><td>0x05E6CDD03D10134B65D5A6e1951ceC98810568ff</td></tr><tr><td>Inverse</td><td>0xEe590e6E3a39FEfaC33F21462938c621C08A8d8c</td></tr><tr><td>KeeperOracleImpl</td><td>0x2530ad2c1d913b857128011FF2fe04D1910E0B97</td></tr><tr><td>MagicValueLib</td><td>0x7f546931252Be883Fe81D304781671d28411a6F8</td></tr><tr><td>MakerVaultFactory</td><td>0xD174C71aBB6De9d71F62eb666921C950c5a81853</td></tr><tr><td>MakerVaultFactoryImpl</td><td>0xB91691A148141f95d0A7b6d3a9eE869bB0300444</td></tr><tr><td>MakerVaultImpl</td><td>0x50E8CbA2cFf5620B3efCB820Aa3D55133b2Ccf73</td></tr><tr><td>Manager</td><td>0xa9AF20277A894EC90BC4EB308eB0B077332DAcd8</td></tr><tr><td>ManagerImpl</td><td>0xD614F92F5980cEcA0CE3Bb61fFae6eF3C907bf68</td></tr><tr><td>MarketFactory</td><td>0xFfB33F838096cF3C3c7dD21c1F941BB2705248E1</td></tr><tr><td>MarketFactoryImpl</td><td>0xC3bE5FcBfDD38f5c6eb5d8cDdE712eb1d54A1Aa1</td></tr><tr><td>MarketImpl</td><td>0xf94F18fe7eF42eee309eBFc287F2f425CB16cBc9</td></tr><tr><td>MarketParameterStorageLib</td><td>0xdA381aeD086f544BaC66e73C071E158374cc105B</td></tr><tr><td>MultiInvoker</td><td>0xbcA65Ce3629167600d52492b61A97627305F4E0e</td></tr><tr><td>MultiInvokerImpl</td><td>0xB900AB6e8c70De1F98955C83d0eb1B7a3ED27a68</td></tr><tr><td>OracleFactory</td><td>0x5f2fc88cC29726D5643072Bf423338D69AE47053</td></tr><tr><td>OracleFactoryImpl</td><td>0x698a736DA508245bbC7830c8A95FfB5C629157f9</td></tr><tr><td>OracleImpl</td><td>0x78f9340bEf2f54CfdEe8b8B4066D60d5A5736EEE</td></tr><tr><td>OrderStorageGlobalLib</td><td>0x831E64292bF41bF0bDbC6D58d9FDd93D7C9396D7</td></tr><tr><td>OrderStorageLocalLib</td><td>0x8Da96a2eDe1dd5Af8Bd3BD142226820f6Bb09751</td></tr><tr><td>OrderVerifier</td><td>0x6b1C4978142A9BC9dD5777866AA8Ad610deD696c</td></tr><tr><td>OrderVerifierImpl</td><td>0xA692e209647f6F8108e2C98Ab8da78940cc93586</td></tr><tr><td>PositionStorageGlobalLib</td><td>0x5bEA99BF18624AA504580546Ac9D9Ac3b9aeb747</td></tr><tr><td>PositionStorageLocalLib</td><td>0xf817521610600c4674364246A5CF4af8e627805D</td></tr><tr><td>PowerHalf</td><td>0x234253280A5427cb9e198367B6804dbA9fCAB7dC</td></tr><tr><td>PowerTwo</td><td>0x7B6b232Cf4FF0f72a0b711d082C532bAF111C982</td></tr><tr><td>ProxyAdmin</td><td>0x2b87C59F5220EE51616Ad2273b5F683D5Ea27cbc</td></tr><tr><td>RiskParameterStorageLib</td><td>0xeea68DbE228210454D4443f4E1B37E842B848C3d</td></tr><tr><td>SolverVaultFactory</td><td>0xAE794C750991b19485E17788d1a19b83BA68bd62</td></tr><tr><td>SolverVaultFactoryImpl</td><td>0x18AD45bdda468259257E46BA07De6cD3d88Cd632</td></tr><tr><td>SolverVaultImpl</td><td>0x4F7A6cCEd29712fc5B102E730C27324a01e74179</td></tr><tr><td>StorkFactory</td><td>0x7A18A52EF9Ab4E2EDE9113ef13483eD18b395ca7</td></tr><tr><td>StorkFactoryImpl</td><td>0x8CDa59615C993f925915D3eb4394BAdB3feEF413</td></tr><tr><td>Stork_CommitmentGasOracle</td><td>0x0a47bb5E5260619204a578Bd477204FcE6246BB7</td></tr><tr><td>Stork_SettlementGasOracle</td><td>0x19A4010E859ca3d10F0d928C6665F9a9E3BE4B22</td></tr><tr><td>Verifier</td><td>0x7AAF9184EE1299226d46fFEB36595Bb8D0EdF753</td></tr><tr><td>VerifierImpl</td><td>0x87984983f1080721F7283d5756fd9D0Ce1fA82D4</td></tr><tr><td>VersionLib</td><td>0x136BbCEc28546b6bf20bF8fac8FB686ea0eE1EF5</td></tr><tr><td>VersionStorageLib</td><td>0x7a98eFCe4A399794aE7524faEb2cc6A8eF730fCF</td></tr></tbody></table>

## External Contracts

<table data-header-hidden><thead><tr><th width="320"></th><th></th></tr></thead><tbody><tr><td><strong>Contract</strong></td><td><strong>Address</strong></td></tr><tr><td>USDC</td><td><a href="https://explorer-sepolia.perennial.foundation/address/0x37Fa204b282e46f54744660bf3dF48b43A554EbC?tab=contract">0x37Fa204b282e46f54744660bf3dF48b43A554EbC</a></td></tr><tr><td>Stork</td><td><a href="https://explorer-sepolia.perennial.foundation/address/0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62">0xacC0a0cF13571d30B4b8637996F5D6D774d4fd62</a></td></tr></tbody></table>


# Bridging to Perennial

{% hint style="info" %}
If you'd like to withdraw from Perennial, see [this page](/guides/bridging-from-perennial)
{% endhint %}

To deposit to Perennial, you are able to choose between two bridges. Each bridge has different speed/costs, so ensure to look at either option when deciding which one to use.

## Using the Intent bridge (\~30 sec)

Using Relay's intent bridge you can deposit from any of the 50+ supported chains. However, this bridge induces slippage so look at the native bridge if you are sensitive to fees.

Link: [Relay.link](https://www.relay.link/bridge/perennial?includeChainIds=8262e08d-57c9-4b4f-8dfe-6c92ee79354e\&fromChainId=8453\&fromCurrency=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913\&toCurrency=0x39cd9ef9e511ec008247ad5da01245d84a9521be)

<figure><img src="/files/rFeoFHSb19SAZOSSd5By" alt=""><figcaption><p>Relay's Intent based bridge</p></figcaption></figure>

## Using the Native Bridge (\~3min)

Using the chain's Native bridge you are able to bridge ETH & USDC from BASE to Perennial. This birdge doesn't have any slippage.\
\
Link: <https://bridge.perennial.foundation/>

<figure><img src="/files/iftnRqOakU2gq2YTija9" alt=""><figcaption></figcaption></figure>


# Create an Account

Follow this guide to get started trading on Perennial. The following steps will help you sign in, open a collateral account, & place a trade.&#x20;

### Step 1: Connect Wallet

<figure><img src="/files/RITuBAgoqZIpV2FxEN6x" alt=""><figcaption><p>Click connect wallet </p></figcaption></figure>

### Step 2: Choose your prefered wallet

<figure><img src="/files/HZ5sBz63RULNV1qgNFGO" alt=""><figcaption></figcaption></figure>

### Step 3: Sign Message

Sign the message when prompted to log into Perennial.

<figure><img src="/files/2nlNr5Q5HSBPJZKzbNhz" alt=""><figcaption></figcaption></figure>

### Step 4: Create Collateral Account

Next you'll be setting up your collateral account. Select "Setup One-Click Trading" to start setting up your Perennial account.

<figure><img src="/files/dHiIfMH8ppUIEeyKGsqN" alt=""><figcaption></figcaption></figure>

### Step 5: Deposit Collateral

Once you have USDC on Arbitrum, you'll be able to deposit tokens into your collateral account.&#x20;

<figure><img src="/files/eg8oUY0K1HT0s2dGYEsw" alt=""><figcaption></figcaption></figure>

*NOTE: A minimum amount of 85 USDC is required due to the $65 USDC minimum positions size & the 10 USDC gas requirement.*

### Step 6: Grant the CA permissions

Send a transaction to register the newly created Credit Account with the Perennial trading system. This allows it to trade on your behalf.

<figure><img src="/files/EZgS5XbPeI7jJHpScMER" alt=""><figcaption></figcaption></figure>

### Step 7: Open your first Trade

Fill out the form on the left & open your first trade!

<figure><img src="/files/ja3eHnQr0pBJHdB8hquj" alt=""><figcaption></figcaption></figure>


# Place a limit order

### Step 1: Enter collateral amount

Type in how much collateral you'd like to use for the trade.

<figure><img src="/files/4YbPvgO9fFpAusiv7ct5" alt=""><figcaption></figcaption></figure>

### Step 2: Enter Limit Price

Enter the price you'd like the order to execute at.

<figure><img src="/files/1sL8OEiOVMsFtJBz2pVi" alt=""><figcaption></figcaption></figure>

### Step 3: Select Leverage

Use the slider to enter the leverage for the position. You can see this change the amout of exposure you'll have in the above input.

<figure><img src="/files/9zssv929IXRlKCP3GHfH" alt=""><figcaption></figcaption></figure>

### Step 4: Place Order

Once ready, select "Place Trade" and follow the prompts to place your limit order.

<figure><img src="/files/sVpLRkIe7hMwdvJ4NSpZ" alt=""><figcaption></figcaption></figure>

### Step 5: Check you open orders

Use the "Orders" tab to check the open orders you have. You can click the X button to cancel them!

<figure><img src="/files/DNqy9arXhTJiHE1kmsz6" alt=""><figcaption></figcaption></figure>

<br>


# Bridging from Perennial

To bridge assets from Perennial to another chain, you are able to choose between two bridges. Each bridge has different speed/costs, so ensure to look at either option when deciding which one to use.

## Using the Fast bridge (\~1min)

{% hint style="warning" %}
Due to the design of Relay's system users can expect some slippage when bridging.
{% endhint %}

Using Relay's intent bridge you can bridge almost instantly from Perennial. This bridge allows you to choose any destination chain that Relay supports, including non-EVM chains.

Link: [Relay.link](https://www.relay.link/bridge/base?includeChainIds=8262e08d-57c9-4b4f-8dfe-6c92ee79354e\&fromChainId=1424\&fromCurrency=0x39cd9ef9e511ec008247ad5da01245d84a9521be\&toCurrency=0x833589fcd6edb6e08f4c7c32d4f71b54bda02913)

<figure><img src="/files/rFeoFHSb19SAZOSSd5By" alt=""><figcaption><p>The Relay.link bridge interface</p></figcaption></figure>

## Using the Native Bridge (\~1 day)

{% hint style="warning" %}
This bridge currently takes 1 day to withdraw from the chain
{% endhint %}

Using the chain's native bridge you can withdraw bridged assets to BASE chain. This bridge doesn't have slippage but requires much more time.\
\
If your balance is still in your Perennial Exchange account, use the following instructions to withdraw from the exchange:<br>

1. Navigate to the [Perennial Account Factory Contract](https://explorer.perennial.foundation/address/0xe69FdDc2c8aDA6BE0ed02aE414f138B8edBC1D1c?tab=read_write_proxy)
2. Enter your wallet address in the input
3. Click "Read" to find your exchange account address
4. Click the resulting address to navigate to your specific Exchange Smart Account
   1\.

   ```
   <figure><img src="/files/QQsKlTLQXljA6ylqskPC" alt=""><figcaption></figcaption></figure>
   ```
5. Click "Contract" then "Read/Write Proxy" then "Connect Wallet" to connect your wallet
   1\.

   ```
   <figure><img src="/files/6cYG6AYMFT1E0FU5j26e" alt=""><figcaption></figcaption></figure>
   ```
6. Scroll down and click "Withdraw"
7. Click "Max" in the first input, and type "true" in the second
   1\.

   ```
   <figure><img src="/files/xXtW7g0o4gNE0i58AlBP" alt=""><figcaption></figcaption></figure>
   ```
8. Click "Write" to send your transaction. Your bridged USDC will now be in your wallet
   1. Use the below bridge to withdraw to Base

Native bridge link: <https://bridge.perennial.foundation/>

<figure><img src="/files/iftnRqOakU2gq2YTija9" alt=""><figcaption></figcaption></figure>


# Markets

Introduction to Markets

Underlying Perennial is a three-sided market, consisting of longs, shorts & makers, that trades synthetic exposure derived from a price oracle, over a given payoff function. Each market is independent & has isolated risk.&#x20;

A Market in Perennial is defined by things like:&#x20;

* [**Oracle**](/protocol/markets/oracles-and-settlement)
* [**Payoff function**](/protocol/markets/payoff-and-positions)
* [**Fee structure** ](/protocol/markets/price-impact-and-trading-fees)
* [**Funding & Interest Rate**](/protocol/markets/funding-and-interest-rate)
* [**Leverage & Liquidation**](/protocol/markets/margin-and-liquidations)

Makers can provide liquidity to the market various ways:

* **Through** [**Vaults**](/protocol/vaults)**:** These are configurable pools that consolidate DSU (a USDC-wrapped stablecoin used as collateral) and deploy it as Maker positions across one or multiple markets, absorbing imbalances from Taker positions.
* **Through Direct Liquidity Provision:** Liquidity Providers (LPs) can also supply collateral directly to specific markets, often utilizing leverage to enhance capital efficiency and potential returns (while also managing associated risks).

Key implications of this design include:

1. **Fully Synthetic Payoffs:** Perennial markets can be created for any asset with a reliable price feed (e.g., crypto tokens, fiat currencies, commodities) or any programmable variation of that feed. The primary practical constraint is the availability of a non-manipulable oracle.
2. **Multiple Markets per Price Feed:** A single oracle (e.g., for ETH price) can support various markets, each with a different payoff function. For instance, there could be a Long-ETH market (payoff: 1\*ETH), a Short-ETH market (payoff: -1\*ETH), and even a 3x Short-ETH market, all referencing the same ETH oracle.
3. **Multiple Markets per Payoff Function:** Due to the isolated nature of each AMM, even for an identical payoff function (e.g., Short-ETH with payoff -1\*ETH), multiple distinct markets can exist. Each of these can have its own unique fee structure, funding/interest rate parameters, utilization curves, and other market-specific configurations.


# Market Design

## Market Mechanism

In V2 of Perennial, markets natively net long positions against short positions, and only utilize maker liquidity to cover the resulting imbalance. This yields markets that are up to an order of magnitude more efficient in terms of open interest to required maker liquidity.

<figure><img src="/files/nMOBeAcCfZeHyk10NzM3" alt=""><figcaption><p>V2 now nets longs &#x26; shorts instead of V1's design which had segregated markets for long &#x26; short payoffs.</p></figcaption></figure>

### Utilization of Maker Liquidity

The maker side of the market is only required to cover the net exposure of the taker side: longs & shorts. Long and short taker positions are first netted out against each other with the resulting exposure directed to the maker pool pro-rata.

<figure><img src="/files/O2xVurAGveQXnBeH29bW" alt="" width="477"><figcaption><p>With 10u long &#x26; 6u short, the maker pool (consisting of 5u total) is taking on 4u short exposure pro-rata or is 0.80x short.</p></figcaption></figure>

### Market Simulator

To help understand how different mixes of maker/long/short effect the market we've built a little simulator. \
\
Try it out for your self here: [Perennial Market Simulator](https://pnl-sim.vercel.app/)

<figure><img src="/files/O1YCVlcUM9Deu94f0wyG" alt=""><figcaption></figcaption></figure>


# Oracles & Settlement

## Oracles

Oracles are the core of each market within Perennial. Each market pulls in one or more prices from oracles to be used in the payoff function.&#x20;

{% hint style="info" %}
While a simple market will just use a single price feed (ex. ETH), more complex market could use payoffs with multiple price feeds (ex. ETH / BTC).
{% endhint %}

Perennial's modular design supports custom oracles. Currently, Perennial markets use an implementation of [Stork's](https://www.stork.network/) low latency oracles, allowing for fast & efficient price updates.&#x20;

## Settlement

[Market payoffs](/protocol/markets/payoff-and-positions) in Perennial are computed directly from oracle prices. To prevent timing advantages or arbitrage against oracle updates, a delay is introduced into the settlement process.

When a user initiates an action to open or close a position, this request is **timestamped**. The actual change to the position doesn't occur immediately. Instead, it remains in a pending state. A **Keeper** later finalizes the trade by providing the oracle price that corresponds to the initial timestamp of the request. Settlement effectively occurs based on this specific oracle price, which is delivered at a subsequent oracle update

{% hint style="info" %}
**Developer Note:**\
The settlement flow happens entirely on-chain, giving strong guarantees for projects building on top of Perennial.&#x20;

Perennial smart contracts store the current version for position adjustments, allowing for the positions opening price & PnL to be retroactively calculated at the next on-chain settlement period (when the contracts are interacted with again), avoiding the need for a second interaction during opens/closing (or the need for a keeper).&#x20;
{% endhint %}


# Payoff & Positions

When a market is initialized, the **Market Operator** selects a specific **payoff function**. This function defines the precise logic the smart contracts use to distribute funds between the long and short sides of the market upon settlement.

Perennial offers developers the flexibility to define virtually any payoff function they wish. This can range from simple long \[asset] or 3x short \[asset] markets to more complex structures like options and other exotic payoffs.

The payoff function for a given market can be any mathematical function operating on an available oracle price feed. This function also defines the nature and magnitude of exposure that one unit (1e18) of a Taker's position represents within that market.

**Example Payoff Functions**

| Product            | Payoff      | Oracle         |
| ------------------ | ----------- | -------------- |
| 3x Leveraged Ether | 3 \* ETH    | Stork ETH Feed |
| Squeeth            | ETH \* ETH  | Stork ETH Feed |
| ETH-USDC UniV2 LP  | sqrt( ETH ) | Stork ETH Feed |

The payoff function for a given market can be any mathematical function operating on an available oracle price feed. This function also defines the nature and magnitude of exposure that one unit (1e18) of a Taker's position represents within that market.

{% hint style="info" %}
IIt's important to note that some payoff functions can be inherently leveraged (e.g., a "3x Leveraged ETH" market where the payoff itself is 3 \* ETH\_price\_change). This leverage is distinct from the leverage that Makers or Takers might employ on their collateral for their positions. For instance, a Maker could be 2x leveraged while providing liquidity to a market with a 3\*ETH payoff function.
{% endhint %}

### Positions

In Perennial, positions are denominated in **units of a payoff function**, not directly in USD. This means a user's exposure is directly tied to the behavior of the chosen payoff function.

For instance, if a user wishes to open a 1 ETH long position where the market's payoff function is 1 \* ETH, they would open a Taker position equivalent to 1 \* market\_payoff. This position would then maintain an exposure equivalent to 1 ETH until it is closed or liquidated.

Conversely, if a user aims to open a position corresponding to a specific USD amount, they must first estimate that USD value in terms of the market's underlying payoff units and then open their position accordingly. \
\
For example, if ETH is approximately $1000, and a user wants to establish a $2500 long-ETH position, they might call openTake(2.5). This action would open a position that tracks 2.5 \* ETH, which would be approximately equivalent to $2500.

[Funding payments](/protocol/markets/funding-and-interest-rate) and[ various fees](/frequently-asked-questions/fees) (such as interest rate fees, price impact fees, and trade fees) are directly debited from or credited to a user's collateral account associated with their position.


# Price Impact & Trading Fees

Price impact and trading fees are distinct charges incurred whenever an account's position changes.

## **Price Impact**

The price impact is the difference between a trade's execution price and the oracle price, applied to Taker positions. It is calculated as the sum of linear, proportional, and adiabatic fees.

```
TradeImpact = LinearFee + ProportionalFee + AdiabaticFee 
```

### Linear Fee

A fixed spread calculated as a percentage of the trader's notional value.

```
Taker Linear Fee = notional × takerLinearFee
Maker Linear Fee = notional × makerLinearFee
```

### Proportional Fee

Varies based on the volume of trades occurring at that time.

```
Taker Proportional Fee = notional × (takerProportionalFee × takerTotal / takerScale)
Maker Proportional Fee = notional × (makerProportionalFee × makerTotal / makerScale)
```

### Adiabatic Fee

Paid by Takers to incentivize a more balanced market, adjusting gradually based on the aggregate market skew and the direction of the Taker's order.

```
takerAdiabaticFee = (signedNotional × takerAdiabaticFeeParameter × (skew' + skew) / 2) / takerScaleParameter
```

Orders are categorized as:

* **Positive skew orders** (long open / short close): Trades that increase or create long exposure, or decrease or close short exposure.
* **Negative skew orders** (short open / long close): Trades that increase or create short exposure, or decrease or close long exposure.

**Key Variables for Price Impact:**

```
notional = abs(positionDelta * latest price)
signedNotional = positionDelta * latestprice
takerLinearFee (parameter) → riskParameter.takerFee.linearFee
takerProportionalFee (parameter) → riskParameter.takerFee.proportionalFee
takerTotal → globalOrder.takerTotal()
takerScale (parameter for proportional fee) → riskParameter.takerFee.scale
takerAdiabaticFeeParameter → riskParameter.takerFee.adiabaticFee
takerScaleParameter (for adiabatic fee) → riskParameter.takerFee.scale
makerLinearFee (parameter) → riskParameter.makerFee.linearFee
makerProportionalFee (parameter) → riskParameter.makerFee.proportionalFee
makerTotal → globalOrder.makerTotal()
makerScale (parameter for maker proportional fee) → riskParameter.makerFee.scale
skew = long - short (market skew before the trade)
skew' = long - short (market skew after the trade)
```

## **Trade Fees**

Trading fees are levied on Perennial and are based on the gross trade fee.

```
Gross TradeFee = TakerFee + MakerFee
```

<figure><img src="/files/aFztoMlxtIqpt5bfVin9" alt=""><figcaption></figcaption></figure>

### **Fees Summary & Distribution**

<figure><img src="/files/JSvPTKKa142f3Es2S12v" alt=""><figcaption></figcaption></figure>

As of v2.3, the calculation of market fees has been updated to decouple risk and oracle fees, with oracle fees now determined by the oracle itself rather than market parameters. Collected fees are split between Makers (and in rare cases Takers), the Perennial treasury, and the respective product owner's treasury.

The apportionment of the `Gross TradeFee` follows this structure:

1. **Subtractive Fee (Referral Component):**\
   `subtractive_fee_amount = Gross TradeFee × referral_fee_percentage`
2. **Solver Fee:**\
   `solver_fee_amount = subtractive_fee_amount × solver_fee_percentage`
3. **Market Fee:**\
   `market_fee_amount = Gross TradeFee - subtractive_fee_amount`
4. **Risk Fee:**\
   `risk_fee_amount = market_fee_amount × risk_fee_percentage`
5. **Oracle Fee:**\
   `oracle_fee_amount = (market_fee_amount - risk_fee_amount) × oracle_fee_percentage`
6. **Protocol Fee:**\
   `protocol_fee_amount = market_fee_amount - risk_fee_amount - oracle_fee_amount`

**Key Parameters for Trade Fees:**

```
takerFeeParameter → marketParameter.takerFee
makerFeeParameter → marketParameter.makerFee
referral_fee_percentage (parameter for subtractive fee)
solver_fee_percentage → intent.fee
risk_fee_percentage → marketParameter.riskFee
oracle_fee_percentage → oracleReceipt.oracleFee
```

### Fee Split

All collected fees are distributed among Makers (occasionally Takers), the Perennial treasury, and the treasury of the respective product owner. This enables market owners (e.g., individual organizations, DAOs, protocols) to earn revenue from the administration of their products and parameters.


# Funding & Interest Rate

In Perennial, funding and interest rates are key mechanisms for maintaining market balance and compensating liquidity providers (Makers). The funding rate incentivizes Takers to balance long and short open interest, while the interest rate compensates Makers for their delta-neutral capital costs.

### Market Skew

Market `skew` measures the imbalance between aggregate long and short Taker positions. A perfectly balanced market (zero skew) maximizes capital efficiency. When an imbalance exists, Makers take on exposure to the lesser side of the market, ensuring the larger side is always backed. The skew is calculated as:

$$
skew = \frac {long - short} {skewScale}
$$

Where:

* `long`: Aggregate long positions.
* `short`: Aggregate short positions.
* `skewScale`: A parameter determined by the Market Operator.

To reduce skew, a funding rate is introduced to incentivize market participants to adjust their positions.

## Funding Rate

The funding rate, r', adjusts based on the market skew and the time elapsed since a position was opened.

<figure><img src="https://lh4.googleusercontent.com/MqpggtMHq7XldXiFpjLfOXPt6LfpRI9sNsOgRwzhvHdsT0-N3rQW8820Zr2bMXIM0hclBSAsnqwpB1-mQsPqs_OnhBLqTGQJ-ozzZEYfabdrdMNLPKiJpFp6klqX8vpKUZwsFimTA2AutArx-XEY6Q" alt=""><figcaption><p>The figure shows an example of how skew in a market can effect the funding rate. </p></figcaption></figure>

{% hint style="info" %}
The maker side has no ability to effect the pricing of the funding, aside from indirectly through limits on the magnitude of long and short.
{% endhint %}

### Calculating the Funding Rate

$$
r' = max(\dfrac{min(r + (t' - t) \* skew}{k}, rMax), rMin)
$$

Where:<br>

* `r'`: Current funding rate.
* `r`: Funding rate when the position was opened.
* `t'`: Current time.
* `t`: Time when the position was opened.
* `skew`: Current market skew (as calculated in 6.1).
* `k`: A risk parameter (pController.k) influencing the rate of change.
* `rMax, rMin:` Maximum and minimum bounds for the funding rate.

If `skew` is positive (more longs than shorts), longs pay shorts. If `skew` is negative, shorts pay longs. The funding rate r' changes linearly with time based on the `skew/k` factor between oracle updates.

### Makers

When there is a skew, Makers supplement the lesser side of the market. In return, they receive a pro-rata share of the funding based on their exposure. The Maker's utilization for funding, mu, is:

`mu → min((long – short) / maker, 1)`

Absolute value is implied if long-short is negative, as Makers cover the net taker imbalance

<figure><img src="/files/RqU8jm9h5XOFTgxaInzh" alt="" width="342"><figcaption></figcaption></figure>

Makers are compensated for taking on the relatively unfavorable side of the market. For instance, if a market has a 40% skew (e.g., 10 units long, 6 units short, `skewScale=10`) and Makers have 5 units of liquidity, they effectively cover 4 units of the net short exposure. If `mu` determines they cover, for example, 80% of this imbalance, they would receive 80% of the funding that the short side (in this case, the side Makers are backing) would theoretically receive per position.

A funding fee (`ff`) is also applied, calculated as:\
`ff → |r'| * marketParameter.fundingFee`\
This fee is paid by Takers and contributes to what Makers receive

## Interest Rate

To incentivize Makers even when the market is relatively balanced, an interest rate (i) can be charged. This is designed to cover Makers' delta-neutral capital costs, distinct from the funding rate which covers net exposure. Takers pay this interest rate, and Makers receive a portion as interest rate fees (ii).

The interest rate is determined by:

`i = U(u) * min(maker, long + short) / (long + short`<br>

Where:

* `U`: A utilization curve function (e.g., Compound-style or jump-rate model) defined by `riskParameter.utilizationCurve`.
* `u`: The market utilization.
* `maker`: The Maker's total position size.
* `(long + short)`: The sum of absolute long and short Taker positions.

The `min(maker, long + short) / (long + short)` term ensures the interest rate is discounted pro-rata if Maker liquidity exceeds the total Taker open interest, capping the spread.

### &#x20;**Interest Rate Fees**

The interest rate fee (`ii`) that Makers receive is:\
`ii → i * marketParameter.interestFee`

### Utilization (u)

Market utilization u feeds into the interest rate calculation. It is determined by comparing two utilization measures: net utilization (`nu`) and efficiency utilization (`eu`).

**Net utilization (nu):**\
`nu = major / (maker + minor)`\
Where major is the larger of long or short Taker positions, and minor is the smaller.

<figure><img src="/files/9R0XptVjZwPD9X1Pmvkc" alt=""><figcaption><p><br>Example: If longs = 10, shorts = 6, maker = 5, then nu = 10 / (5 + 6) = 10 / 11 ≈ 91%.</p></figcaption></figure>

**Efficiency utilization (eu):**\
`eu = (major * el) / maker`\
Where `el` is the `riskParameter.efficiencyLimit`. This measures how efficiently Maker liquidity offsets demand on the larger side.

The final utilization u used in the interest rate formula is:\
`u = min(1, max(nu, eu))`\
This selects the greater of nu or eu (capped at 100%) to drive the interest rate via the `U(u)` curve.

## **Total Payments and Receipts**

The total funding and interest-related payments for Takers and receipts for Makers are:

**Long Takers Pay:**\
`longPays = r' + ff/2 + i`

* They pay the current funding rate `r'`, half of the funding fee `ff/2`, and the interest rate `i`

**Short Takers Pay (or Receive if r' is positive):**\
`shortPays = -r' + ff/2 + i`

* They pay the negative current funding rate -r' (i.e., receive if r' is positive, pay if r' is negative), half of the funding fee ff/2, and the interest rate i.

**Makers Receive:**\
`makerReceives = mu * r' - |mu| * ff/2 + i - ii`

* They receive their pro-rata share of the funding rate `(mu * r')`.
* They contribute their pro-rata share to the funding fee pool `(-|mu| * ff/2).`
* They receive the gross interest paid by Takers `(i)`.
* A portion of this interest `(ii)`is the net interest fee they retain. The difference `(i - ii)` may go to the protocol or other designated parties.


# Margin & Liquidations

## Margin

Makers and Takers have the ability to trade in a more capital-efficient manner by using leverage. Because trading with leverage means that a participant's notional exposure may far exceed the amount of collateral provided, a risk mitigation mechanism is required via margin and liquidation to prevent insolvency.

In Perennial, the Market Operator sets the parameters `maintenance`, `margin`, `minMaintenance`, and `minMargin`.

* `margin` and `minMargin` define the ratio and minimum dollar amount (respectively) of collateral required to open or change a leveraged position (i.e., initial margin).
* `maintenance` and `minMaintenance` define the ratio and minimum dollar amount (respectively) of collateral that is required to maintain a leveraged position and prevent it from being liquidated (i.e., maintenance margin).

These parameters set how much notional exposure a Maker can provide and how much leverage a Taker can obtain. Based on these parameters, Makers' and Takers' initial margin and maintenance requirements are defined by:

`marginRequirement = max(position * price * margin, minMargin)`\
`maintenanceRequirement = max(position * price * maintenance, minMaintenance)`<br>

For example, if the `maintenance` (ratio) is set at 20%, then the maximum leverage a Taker could obtain would be 5.0x (1 / 20% = 5). Assuming the price of ETH is $1000, the table below shows the maintenance margin required according to the notional positions for a Long-ETH product:

<table><thead><tr><th width="150">Side</th><th width="140.03515625">Position</th><th width="184.6153846153846">Notional</th><th>Maintenance</th><th>Leverage</th></tr></thead><tbody><tr><td>Maker</td><td>10</td><td>$10,000</td><td>$2,000</td><td>5x</td></tr><tr><td>Taker</td><td>5</td><td>$5,000</td><td>$1,000</td><td>5x</td></tr></tbody></table>

## Liquidations

An account can be liquidated whenever its collateral drops below the `maintenanceRequirement` for their position.

As is the case with other position changes, a liquidation must sit in a pending state until the next oracle update. However, a special lock is placed on the account during this period of pending liquidation so that the liquidation process cannot be interfered with. The user may not open or close a new position (or be liquidated again) until the liquidation process is completely settled and the lock is cleared.

A minimum level of `margin`, `minMaintenance`, is set such that all non-zero positions must have enough collateral to incentivize a liquidation—even in cases where a position becomes undercollateralized. The `maintenanceRequirement` is always no less than the `minMaintenance`. For risk management purposes, the maintenance requirement for Makers is calculated by assuming 100% utilization of their exposure.

When a position is successfully liquidated, the liquidator can withdraw a fee from the collateral account. The liquidation fee is a parameter that is calculated as a multiple of the settlement fee. The liquidation fee is optional as self-liquidations are permitted. Perennial does not take a protocol or product owner cut of the liquidation fee.

The table below provides an example of the liquidation reward (fee) that can be collected (Assuming a 20% liquidation reward:

| Collateral ($) | Maintenance Requirement ($) | Liquidation Reward ($) |                          |
| -------------- | --------------------------- | ---------------------- | ------------------------ |
| 10,000         | 15,000                      | 3,000                  | Eligible for liquidation |
| 30,000         | 32,000                      | 6,400                  | Eligible for liquidation |
| 25,000         | 20,000                      | N/A                    | Safe (above requirement) |


# Liquidity Provisioning

On Perennial LPs can provide liquidity with up to 50x leverage.

Rather than a protocol or 3rd party managed vault, Liquidity Providers (LPs) may choose to LP directly into markets. This can be beneficial for the following reasons:

**Leverage**

When providing liquidity directly to the markets you are able to be more efficient with your collateral by using leverage. Instead of making with X units of collateral, you can use leverage to multiply that amount. This nets an LP more fees & interest than LP'ing without leverage. \
\
However, this comes with liquidation risks. For professional LPs its relatively simple to ensure that you are hedged by watching the markets and rebalancing your collateral between venues as needed.&#x20;

**Lower "At-Risk" Collateral**\
\
A side effect of LP'ing with leverage is that there is less "capital at risk" in the protocol's contracts. In the event of a bug/hack there is less collateral exposed to the issue than LP'ing without leverage.

### Risk Management&#x20;

When LPing with leverage extra care needs to be taken to ensure your position isn't liquidated. Normally, advanced makers will use external systems to monitor their position to calculate their exposure & the health of their leveraged LP.&#x20;

Included in Perennial's [Typescript SDK](https://github.com/equilibria-xyz/perennial-sdk-ts) we have a number of helper functions that can do the heavy lifting when it comes to fetching and understanding your position. We also have an [example script](https://github.com/equilibria-xyz/perennial-sdk-ts/blob/main/examples/onchain/fetchFormatMakerData.ts) that can help you get started quickly. \
\
Once you have this data you're able to setup strategies to monitor and react to market changes.

### Position Settlement & Hedging&#x20;

Professional LPs will usually try to hedge their exposure when making a market. In Perennial's markets, a maker's exposure can change significantly within the space of 15seconds due to high leverage and fast settlement. So its crucial that makers have an understanding of settlement within the a given Perennial market. See the [Settlement](/protocol/markets/oracles-and-settlement#settlement) section for more info.

Practically there are two ways to approach hedging: Track every position change on a market by watching the `Updated()` event and reacting to those resulting changes, or waiting for the next settled market state, signified by `PositionProcessed`, before hedging.&#x20;

The first option allows for a exposure to be calculated in "realtime" and gives the maker the opportunity to hedge as positions are submitted. The caveat here is that there are uncommon scenarios where the entire epoch is invalid, then the position changes are nullified and will need to be submitted again. To ensure settlement is achieved a maker can watch for `PositionProcessed` event.

The second option is to delay until the next market state is settled. This means the maker may have unhedged exposure for 10-20 seconds but they can be confident that the position changes have been finalized.&#x20;

### How to be an Advanced LP

**Via the UI:**&#x20;

<figure><img src="/files/oMOGpnIynjjmAezX5KRn" alt=""><figcaption></figcaption></figure>

Using [app.perennial.finance](https://app.perennial.finance/make) app you can use the Make page to configure your Advanced LP position.

**Via the Contracts:**

The other option is to write a contract or an integration to create your leveraged Maker position. The leveraged maker position is functionally similar to a long or short order, in that you have collateral and you are able to specify your position size. From there its up to you to calculate the liquidation range & maintain you enough collateral. \
\
See the [Contract Integration](/building-on-perennial/smart-contract-integrations) section for more information on how to create orders.


# Advanced Order Types

Learn about the different type of limit order on Perennial.

## Overview

The Order system provides functionality for creating and managing various types of orders in a decentralized trading platform. It supports limit orders, stop-loss orders, and take-profit orders, each with its own specific parameters and behavior.

#### Order Types:

1. Limit Order
2. Stop-Loss Order
3. Take-Profit Order
4. Cancel Order

### Using Order Types

For standard users, these order types can be placed on the [Perennial ](https://app.perennial.finance/trade)web app.&#x20;

For developers, anyone can create, sign and publish these orders. The easiest way to do so through the Typescript [Perennial SDK](https://github.com/equilibria-xyz/perennial-v2-sdk-ts/).&#x20;

### Execution System via Keepers

Perennial V2 employs an Order Keeper system to ensure efficient and timely execution of orders. Order Keepers are external agents that monitor the market and execute orders when they become eligible, playing a crucial role in maintaining a responsive trading environment.

Perennial has open sourced an example Keeper system which could be optimized significantly. Please feel free to take and modify this system: [Github](https://github.com/equilibria-xyz/perennial-v2-keepers?tab=readme-ov-file)

### Order Types & Arguments

#### Base Arguments (BuildTriggerOrderBaseArgs)

All order types share these common arguments:

```typescript
export type BuildTriggerOrderBaseArgs = {
  address: Address
  marketAddress: Address
  side: PositionSide
  delta: bigint
  maxFee?: bigint
  interfaceFee?: InterfaceFee
  referralFee?: InterfaceFee
}
```

#### 1. Limit Order

```typescript
export type BuildLimitOrderTxArgs = {
  limitPrice: bigint
  triggerComparison: TriggerComparison {
    lte = 'lte',
    gte = 'gte',
  }
} & BuildTriggerOrderBaseArgs
```

A limit order allows traders to specify a price at which they want to buy or sell an asset. The order will only be executed if the market price reaches or surpasses the specified limit price.

#### 2. Stop-Loss Order

```typescript
export type BuildStopLossTxArgs = {
  stopLossPrice: bigint
} & BuildTriggerOrderBaseArgs
```

A stop-loss order is designed to limit an investor's loss on a position. It's triggered when the market price reaches a specified stop price, helping to minimize potential losses.

#### 3. Take-Profit Order

```typescript
export type BuildTakeProfitTxArgs = {
  takeProfitPrice: bigint
} & BuildTriggerOrderBaseArgs
```

A take-profit order is used to lock in profits by automatically closing a position when the market price reaches a specified target price.

### Additional Data Structures

#### CancelOrderDetails

```typescript
export type CancelOrderDetails = { 
  market: Address
  nonce: bigint 
} | OpenOrder
```

### Using the SDK

Perennial has released a Typescript package on NPM to help developers interact with the protocol

```typescript
const marketOracles = await sdk.markets.read.marketOracles()
const marketSnapshots = await sdk.markets.read.marketSnapshots({...})
const ethMarketSnapshot = marketSnapshots.market[SupportedMarket.eth]
const ethUserMarketSnapshot = marketSnapshots.user[SupportedMarket.eth]

sdk.markets.write.placeOrder({
  marketAddress: ethMarketSnapshot.market,
  address: getAddress(<User address>),
  // As with `modifyPosition`, marketSnapshots and marketOracles are optional but recommended.
  marketSnapshots,
  marketOracles,
  orderType, // See `OrderTypes` enum for options
  side, // Position side
  limitPrice,
  stopLossPrice,
  takeProfitPrice,
  collateralDelta,
  delta, // Position size delta
  cancelOrderDetails, // Optional list of existing orders to cancel
  triggerComparison, // Comparator used for order execution. See `TriggerComparison` enum for options
  limitOrderFees,
  stopLossFees,
  takeProfitFees
})
```

### Important Notes

* All order-related functions require the user's address, chain ID, and a public client for interaction with the blockchain.
* The system uses BigInt values for prices and amounts to ensure precision in financial calculations.
* Interface fees and referral fees can be optionally specified for orders.
* The system interacts with a MultiInvoker contract to execute order-related actions on the blockchain.
* Stop-loss and take-profit orders require a negative delta, as they are used to close positions.

This order system provides a flexible and comprehensive set of tools for managing various types of orders in a decentralized trading environment, allowing traders to implement complex strategies and manage their risk effectively.


# Collateral

Perennial is built upon the stablecoin: Digital Standard Unit (DSU).&#x20;

Think of it as *USDC+*. DSU has all the properties of USDC + additional censorship-resistance properties that protect users of DSU & the protocols that build upon it.&#x20;

Properties of DSU:

* Fully collateralized
* 100%+ backed by USDC (and 1:1 redeemable for USDC)&#x20;
* Trust-minimized USDC

DSU is a wrapped version of USDC (deposit 1 USDC, get 1 DSU). DSU is an ERC-20 that can that can then be used in DeFi and redeemed at any time for 1 USDC.&#x20;

When the DSU protocol receives USDC, it deposits it into a DeFi protocol (namely Compound) that is liquid, battle-tested, and safe from a regulatory perspective.&#x20;

The core benefit of this: DSU wrapping minimizes trust assumptions in dollar-backed stablecoins (without impacting UX) and reduces risk associated with upstream protocols, making it an ideal stablecoin primitive to build upon.

### Use in Perennial

**Most Perennial users will not have to directly interact with DSU.**  When a user uses the Perennial frontend with USDC as collateral, Perennial automatically wraps USDC into DSU and deposits the DSU into the protocol. When a user withdraws their collateral, Perennial will unwrap the DSU and return USDC to their wallet.

**If a user is directly interacting with the Perennial smart contracts, they will need to obtain DSU to open Maker/Taker positions.** This can be done by wrapping/unwrapping directly through the DSU smart contracts ([see here](https://github.com/emptysetsquad/emptyset)). Alternatively, for gas efficiency, developers can use the Batcher contract (see [Deployed Contracts](broken://pages/X5Cb9FpZY7jalA7NzXzL)) to wrap/unwrap. &#x20;

### More info:

Website: [dsu.money](https://www.dsu.money/)

Docs: <https://docs.dsu.money/>


# Intents

Perennial's Intent system is focused on giving traders & makers a near CEX like experience when utilizing the protocol. Perennial can achieve this leveraging Intents while also maintaining the liveliness & security guarantees that crypto users demand.&#x20;

Intents allow users to submit trades as EIP-712 signed messages which will then be executed onchain by a Maker. The Maker will take the other side of the trade to flatten the skew created by the intent then settle the positions onchain to the underlying Market's AMM.

## Benefits

* **Guaranteed execution price** - Intents allows traders to specify the exact price at which they want to execute their trades. Whether Market or Limit, these trades are filled by Solvers and settled into the AMM atomically.
* **Broader Liquidity** - Makers can offer quotes on orders across all of Perennial markets from a single collateral pool. Expanding liquidity for traders and reducing complexity for makers.
* **No Passive Exposure** - Rather than passively taking maker exposure in the AMM, Makers can actively choose which intents to make and receive exposure for.


# Mechanism

Perennial's Intents are signed EIP712 messages which are verified by a market contract to modify a user's position. When an Intent is executed it becomes a normal position within a market that subject to the same fees and liquidations as a position submitted onchain.\
\
What makes Intents unique is that they are **priced directly with the maker** executing the order. **Takers** are guaranteed the price they submit, inclusive of fees. The pricing occurs without the intervention of the Market's AMM as the **Maker** takes the inverse of the order.&#x20;

Lets dive into some details:

### Collateral

As is standard in Perennial, all actors in the system must first deposit collateral to back their respective positions. Given this, an intent is only valid if the account associated with the intent has collateral in that corresponding market.&#x20;

### Flat Skew&#x20;

When executing a **Taker's** intent, the **Maker** *must* take the other side of the intent for it to be settled down to the AMM. This ensures that the **Taker's** intent has no impact on the AMMs price.&#x20;

<figure><img src="/files/QrAPmOc35sbwlUrwJXoD" alt=""><figcaption><p>A users &#x26; maker's intents being added to a market .</p></figcaption></figure>

In the above example a **Taker** wants to open a 10 Long intent, the **Maker** must open a 10 Short position to keep the skew the same.&#x20;

### Intent Structure

Intents take the form of a signed EIP-712 signed message.  You can see more [here](/protocol/intents/specification#intent-structure).


# Offchain Infrastructure

Perennial's Intent specification focuses on the onchain mechanism that make intents possible. Interfaces, Makers and/or Infrastructure provides are welcome to implement their own offchain system that efficiently handles & distributes Perennial's Intents.\
\
However when designing the Intent system, an example **Solver API** used:

## Market Orders

<figure><img src="/files/Ut5DKUjADUB5LEH2mOKF" alt=""><figcaption><p>An example offchain flow for Intents describing market orders</p></figcaption></figure>

The above diagram describes a centralized Solver API for:

1. Accepting, aggregating & distributing information about the pricing of **Maker** liquidity
2. Accepting a signed Intent from a **Taker** & returning it to the originating **Maker**&#x20;
3. The execution of the Intent order by the **Maker**

### Key Concepts

#### Continuous Pricing

**Makers** within the system continuously post arrays of order sizes and their corresponding prices to the **Solver API**. The quotes they post are valid for 30 seconds. These prices include all fees accrued by the **Maker** when executing this order to ensure the user gets guaranteed execution at the quoted price.

These prices are then aggregated by the Solver API and pushed out to all subscribed **Takers**. The **Taker** will input the size of their transaction, the price for that order size will be shown, they then sign and return the order to **Solver API** which relays it to the maker for execution.

#### Fill Rate

Not pictured in the diagram, but crucial for the operation of the **Solver API** is a "fill rate". Where **Makers** must maintain a minimum fill rate (filled intents / signed intents returned) when participating in the Solving system. This grants some flexibility in cases of extreme price movement, while ensuring a good trading experience to the **Takers**.

## Trigger Orders

<figure><img src="/files/5l0NTW42YjhmDUZ1wnl7" alt=""><figcaption><p>An example offchain flow for Intents describing trigger orders</p></figcaption></figure>

The above diagram describes a flow for a Solver API to handle trigger Intents:

1. **Taker** publishes signed intent with direction, size, and desired execution price to the **Solver API**
2. **Makers** poll the **Solver API** periodically, and when they find an intent with a desirable price, they execute the transaction.&#x20;

### Key Concepts

#### Competitive Fills

In order to ensure reasonable execution for **Takers**, its key that the trigger orders are shared amongst all **Makers** within the Solving system. In a scenario where there is a single **Maker** in the Solving system, a **Takers** intent may be neglected for the benefit of the **Maker**.

#### Culling Invalid Orders

Periodically the **Solver API** should review the submitted trigger orders for validity. This includes things like the expiry of the order but also the collateral balance of the **Taker** which has submitted the Intent order.&#x20;


# Intent Solvers (Makers)

For actors looking to solve **Taker** intents there are some things that must be considered when developing systems to do so.

### Position Flipping

Due to an invariant on the protocol side, a wallet can't flip their position from Long to Short & visa versa without waiting for the protocol to settle in between. Given this, Makers looking to handle long & short flow should maintain two wallets and net the flow.&#x20;

For example:

| Action          | Long Wallet (Maker) | Short Wallet (Short) |
| --------------- | ------------------- | -------------------- |
| Short 1 BTC     | +1 BTC              | -0 BTC               |
| Short 1 BTC     | +2 BTC              | -0 BTC               |
| Long 1 BTC      | +1 BTC              | -0 BTC               |
| Long 2 BTC      | +1 BTC              | -2 BTC               |
| Maker Rebalance | +0 BTC              | -1 BTC               |

This is unwanted complexity for the **Maker** and we will look to fix this in a later version of the protocol.&#x20;

### Single Position per Market

An invariant of the protocol is that an account can't have multiple positions open in a market at the same time. Instead, a wallet can increase or decrease their position to modify their exposure.&#x20;

This is an intended behaviour of the protocol & will continue to persist.


# Specification

Perennial's intent system has a light footprint onchain. It uses a few modules ot extend the standard `update()` functionality of the markets.&#x20;

## Intent Structure

Intents take the form of an EIP-712 signed message. Below is the structure of an intent order:

```json
{
  "amount":            // The size and direction of the order being opened by the taker
                       //       - Positive opens long / Negative opens short
                       //       - The maker will open the opposite side of the order
                       //       - To close, open an order in the opposite direction
  "price":             // The price to execute the order at
  "fee":               // The solver fee, a percentage of the substractive interface fee
  "originator":        // The referral address of the originator of the order (ex. the interface)
  "solver":            // The referral address of the solver of the order (ex. the router)   
  "collateralization": // The minimium collateralization ratio that must be maintained after the order is executed
  "common": {
    "account": // The target account of the message (usually the account on behalf of which the action is being performed)
    "signer":  // EOA signing the message (usually either the account or a delegate of the account)
    "domain":  // ensures the message is unique to a particular protocol version, chain, and verifier
    "nonce":   // per-sender nonce which is automatically cancelled upon validation
    "group":   // per-sender nonce which must be manually cancelled with a GroupCancellation message
    "expiry":  // prevents this message from having the intended effect after a specified timestamp
  }
}
```

## Market - Update()

These signed Intents submitted by a **Maker** to the intent specific `update()` function on each market instance.&#x20;

```solidity
/// @notice Updates both the long and short positions of an intent order
/// @dev - One side is specified in the signed intent, while the sender is assumed to be the counterparty
///      - The sender is charged the settlement fee
/// @param account The account that is filling this intent (maker)
/// @param intent The intent that is being filled
/// @param signature The signature of the intent that is being filled
function update(address account, Intent calldata intent, bytes memory signature) external nonReentrant whenNotPaused {
    if (intent.fee.gt(UFixed6Lib.ONE)) revert MarketInvalidIntentFeeError();

    verifier.verifyIntent(intent, signature);

    _updateIntent(
        account,
        address(0),
        intent.amount.mul(Fixed6Lib.NEG_ONE),
        intent.price,
        address(0),
        address(0),
        UFixed6Lib.ZERO,
        UFixed6Lib.ZERO,
        true,
        false
    ); // account
    _updateIntent(
        intent.common.account,
        intent.common.signer,
        intent.amount,
        intent.price,
        intent.originator,
        intent.solver,
        intent.fee,
        intent.collateralization,
        false,
        true
    ); // signer
}
```

See the file [here](https://github.com/equilibria-xyz/perennial-v2/blob/v2.3/packages/perennial/contracts/Market.sol#L144)

## Intent Verifier

Key to operation of the intent system is the intent verifier. This contract checks the validity of the intent, the signature, and if the signer is approved as a signer on the account.

You can learn more about this module [here](https://github.com/equilibria-xyz/perennial-v2/tree/v2.3/packages/perennial-verifier)

## Other Modules

* [Trigger Orders](https://github.com/equilibria-xyz/perennial-v2/blob/v2.3/packages/perennial-order/README.md) - A specification for trigger based orders in Perennial
* [Collateral Accounts](https://github.com/equilibria-xyz/perennial-v2/tree/v2.3/packages/perennial-account) -  A collateral management system that enables 1-click-trading


# Collateral Accounts

Collateral accounts help users manage collateral across Perennial markets on a single chain in a gas-less manner. Colloquially called "1-click-trading".

The majority of actions are performed using [EIP-712](https://eips.ethereum.org/EIPS/eip-712) message payloads submitted to keepers through a relayer. Users may self-sign their messages or delegate one or more signers.

### Benefits

* **Gasless Trading** - Moving collateral among markets can now be done with signed EIP712 transactions.
* **Bundled actions** - Multiple different collateral actions can be bundled into a single transaction.
* **Dynamic Rebalancing** - **LPs** can leverage the rebalancing deatures of collateral accounts to automatically shift collateral between markets.

### Account Creation

Account creation was designed to be as flexible as possible. Rather than requiring a transaction from an EOA send a transaction, a user can instead just send USDC to the deterministic address of the future collateral account & rely on a relayer to execute the creation.&#x20;

#### Process:

* Get deterministic address from Controller contract.
* Before the account is created, transfer DSU or USDC to that address for keeper compensation.
* Send a message to the relayer requesting account creation.

Note: A user's EOA may deploy only one collateral account.

### Collateral

All USDC in the account is implicitly wrapped to [DSU](/protocol/markets/collateral) when transferring an amount greater than the account's [DSU](/protocol/markets/collateral) balance into a market. Funds transferred out of markets are not unwrapped until withdrawal.&#x20;

### Implementation

You can see the implementation of this system [here](https://github.com/equilibria-xyz/perennial-v2/tree/v2.3/packages/perennial-account)


# Vaults

Rather than entering multiple markets manually, Liquidity Providers can provide liquidity to markets via a vault. Vaults abstract away some of the complexities of Perennial's core protocol, allowing for a more seamless experience.

At a base level Vaults consolidate collateral & open **Maker** positions on markets. They take on delta (directional) exposure exposure when there is an imbalance between long & short. In exchange, they receive interest & funding from markets they are making.

{% hint style="info" %}
LP's still have the option to LP directly into markets (pick and choose markets, customize position parameters, etc.). See [Advanced LP](/protocol/markets/liquidity-provisioning)
{% endhint %}

Vaults can be configured to supply liquidity to either one or multiple markets by the vault owner. The exact division of liquidity into each market is also configurable.&#x20;

This allows for a number of benefits unique to Perennial:

### Bootstrapping Markets

The cold start problem in derivates is a significant challenge for creating new markets: no liquidity -> no trading volume -> no liquidity.&#x20;

With vaults, nascent markets can be bootstrapped by the vault owner provisioning excess liquidity from existing markets to new markets.&#x20;

### Diversified Yield&#x20;

Vaults enable liquidity providers to receive yield from multiple markets at once. This simplifies the liquidity provisioning for a solo provider and can provide more consistent returns from multiple markets instead of a single one.


# Codebase

Perennial V2 has been designed to be as modular as possible, allowing for horizontal scaling to many markets, oracles & vaults.&#x20;

### Ownership Hierarchy&#x20;

In terms of structure, the protocol owns three factories covering Markets, Oracles & Vaults. The protocol owner can use these factories to spawn new markets, exotic oracles & vaults to direct liquidity. \
\
Additionally, the protocol owns the Multi Invoker (an Operator contract for the UI)

<figure><img src="/files/eGcgIEkA3W4ammwgsq6d" alt=""><figcaption><p>A hierarchical ownership tree for the perennial protocol.</p></figcaption></figure>

### Standard Market Flow w/ MultiInvoker

When a user interacts with a market using the MultiInvoker they are able to bundle a number of steps required to modify their position.

<figure><img src="/files/92ACkPale3TJtO7WPuva" alt=""><figcaption><p>A user takes a 1 unit position in a market.</p></figcaption></figure>

### Standard Vault flow w/ MultiInvoker

When a user interacts with a Vault they generally follow this flow to adjust the vault balances between markets.

<figure><img src="/files/X7J0mP987uae7TwR4aEn" alt=""><figcaption></figcaption></figure>


# Protocol Risks

Perennial V2 was designed to minimize situations where makers or takers are at risk of loosing exposure to markets. However, in very specific situations certain conditions can cause the protocol to limit functionality or reduce exposure. See the two cases below:

### **Taker OI approaches Maker OI --> Maker positions cannot be closed**

Perennial works the same way as Compound or Aave when utilization is high. Rates are increased dramatically to increase liquidity (and incentives demand to reduce exposure). However, it is possible that this could result in a liquidity crunch, where makers are unable to close positions because doing so would push utilization over 100%.&#x20;

However, this type of event is unlikely to occur, and if it were to occur, would likely be very short-lived. Perennial's funding-rate mechanism is specifically designed to combat this situation. If taker utilization ever approaches (or exceeds) 100%, the funding rate aggressively increase toward it's max value (a parameter intentionally set extremely high) such that arbitrageurs provide additional liquidity to take advantage of the high yield (perhaps offsetting on a CEX to avoid risk) and/or takers close positions to avoid paying a high funding rate.&#x20;

### Takers OI  > Maker OI --> PnL Socialization

Even though Perennial caps takers open interest at maker open interest, in the event LPs are highly leveraged & taker utilization is high, it is possible that enough maker positions would be liquidated such that there are more taker positions outstanding than maker positions. If this were to occur, Perennial resolves via PnL socialization, meaning takers would have pro rata exposure to maker positions. During this time, takers are able to reduce open interest, but they would not be able to increase open interest.&#x20;

{% hint style="info" %}
This would be exactly the opposite of how the system typically works, where makers get pro-rata exposure to taker positions
{% endhint %}

Similar to the edge case above (taker OI approaches maker OI), the economics of the system are designed to quickly reverse this case.&#x20;

***

For both cases, These should be viewed as very rare situations, and Perennial has internal & external mechanisms at play to prevent and/or quickly reverse the situation to return the protocol to normal operation.&#x20;


# Why Perennial?

![](/files/uNP8aV6SW4AxmTASzQVV)

Perennial is designed to be a minimalist protocol that is supported by a whole ecosystem of products built on top, each creating a unique experience for a specific subset of users.  This includes things like LP yield vaults, novel financial products (especially structured products), and new protocols that leverage the power of derivatives under the hood.&#x20;

### Why build on Perennial?&#x20;

**Cheapest place to hedge (or get exposure)** — Perennial's mechanism is designed to be as efficient as possible for those using Perennial as a building block. This means perennial has no/low transaction fees (so cheap rebalancing), low funding fees, and no price impact from big buys/sells.&#x20;

**Easiest place to hedge** — Unlike all the trading products out there that are hard to use in DeFi products (too expensive or hard to integrate), Perennial was initially designed with developers in mind. Our code is clean & integrations are easy. Perennial is built with the hooks developers need to build the next generation of hedged vaults and structured products.&#x20;

**Modular + fully synthetic** — Perennial markets are maximally flexible. As long as there is a price feed, any market can be created. The parameters and structure of each market can be fully customized (and is built for plug & play features).

## Integration Pathways

<table data-view="cards"><thead><tr><th align="center"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td align="center"><strong>Building a Frontend</strong></td><td><a href="/pages/Xx2GTBRRAGb2RltEzsUG">/pages/Xx2GTBRRAGb2RltEzsUG</a></td></tr><tr><td align="center"><strong>Building an Operator</strong></td><td></td></tr><tr><td align="center"><strong>Contract Integration</strong></td><td><a href="/pages/IrbfS80U5CBJX9O5UV2F">/pages/IrbfS80U5CBJX9O5UV2F</a></td></tr></tbody></table>


# Before Integrating

We would recommend having a full read through of the Perennial mechanism to get a good idea of how things work. In this section, we'll call attention to some of the nuances of Perennial that developers may encounter.&#x20;

### USD Collateral Only

Perennial only allows for collateral in USD (namely, USDC/DSU) & all P\&L is settled in the collateral account. See the [Maintenance section](/protocol/markets/margin-and-liquidations) for more info on collateral requirements.

However, developers can build on top of other borrow / lend protocols to use other tokens as collateral (ex. deposit ETH into compound, borrow USDC and deposit it as collateral on Perennial).&#x20;

### Delayed Settlement

In order to ensure the consistency & safety of the markets in Perennial, order settlement is delayed. While this increases complexity when it comes to integrating, the reduction in risk is worth it. To learn more about the settlement flow see the [Settlement](/protocol/markets/oracles-and-settlement) section.

Functionally, you can check the settlement of your pending position update by waiting for the timestamp that have been emitted by [`Updated()` ](https://github.com/equilibria-xyz/perennial-v2/blob/main/packages/perennial/contracts/Market.sol#L298)to be included in an oracle version. This can be checked by passing the timestamp to [`at(timestamp)`](https://github.com/equilibria-xyz/perennial-v2/blob/main/packages/perennial-oracle/contracts/Oracle.sol#L65) function to the market's oracle and receiving a version back.

**Failure to settle:**

In rare circumstances settlement can fail. There are two possible scenarios when this can occur:

* Oracle has no price
* The keeper fails to commit a price within the required timeframe.

In this situation, all position updates for that epoch will need to be resubmitted.&#x20;

### Operators

Within the protocol, Operators are special entities that users can approve to control their accounts at the factory level. For market operations, the user must approve the Operator to the MarketFactory & for vaults, the VaultFactory. Once approved, operators can modify accounts for all across all markets or vaults owned by the approved factory contract.

{% hint style="danger" %}
Since operators act on behalf of users any bugs in the operator contract can effect all users that have approved it. Please ensure safe practices when building operators!
{% endhint %}

Operators allow for user experience enhancements while keeping the core functionality of the protocol streamlined. For example:&#x20;

* An operator could allow users to batch operations using `multicall[]`
* An operator could add custom order types, executing market operation when conditions are met in the operator contract.
* An operator could consume signed market order to enable gasless transactions for its users.&#x20;

An Operator could be a contract or an externally owned account. While it's in the spirit of the protocol to build an operator as contract, it is possible to have an EOA act as an Operator. This would greatly reduce transparency & push security assurances off chain, so be thoughtful when implementing such Operators.

### Unmatched Markets

**Though unlikely, it is possible for takers to not be matched 1:1 with makers** (meaning taker exposure) would be less than 100%. See the [Profit and Loss section](/protocol/protocol-risks) for more info. Perennial has mechanisms & procedures internal & external to the protocol to prevent. And in the event it does occurs, it is likely to be extremely short-lived (arbitrageurs have a huge incentives to close the gap ASAP).&#x20;


# Frontend & Client Integrations

{% hint style="info" %}
Anyone is able to create a UI for Perennial. The markets are open for all to interact with & the platform has a method to charge extra fees on flow originating from a particular UI.&#x20;
{% endhint %}

Integrating Perennial as the underlying markets infrastructure for a new product can reduce the technical burden for developers & improve time to market.&#x20;

While the Perennial team initially created the first markets and user interface, we welcome projects to integrate with the Perennial protocol to tap into its liquidity & leverage it's robust design.

## Software Development Kits

Perennial has two SDKs available to help developers get started quicker. The most fully featured SDK written in Typescript an is utilized across most of the client integrations.&#x20;

Additionally, a Python based SDK has been created to assist Makers & Algorithmic traders with their workflows.

<table data-card-size="large" data-column-title-hidden data-view="cards"><thead><tr><th></th><th align="center"></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td></td><td align="center"><a data-footnote-ref href="#user-content-fn-1"><strong>Typescript SDK</strong></a></td><td></td><td><a href="https://github.com/equilibria-xyz/perennial-v2-sdk-ts/">https://github.com/equilibria-xyz/perennial-v2-sdk-ts/</a></td></tr><tr><td></td><td align="center"><strong>Python SDK</strong></td><td></td><td><a href="https://github.com/equilibria-xyz/perennial-v2-sdk-py">https://github.com/equilibria-xyz/perennial-v2-sdk-py</a></td></tr></tbody></table>

These SDKs will abstract away a large portion of the complexity when integrating Perennial into a client application. However if you'd prefer to interact directly with markets you can look at the [#multiinvoker.sol](#multiinvoker.sol "mention")section.

## Adding Application Fees

Applications utilizing Perennial's `MultiInvoker.sol` contract are able to add fees to their order bundles. This allows application developers to focus on creating a great experience for traders/LPs on the front end without having to write Solidity to collect fees on order flow.

See the [#multiinvoker.sol](#multiinvoker.sol "mention")section to learn more

## MultiInvoker.sol&#x20;

In order to reduce the amount of transactions required to interact with the protocol & simplify the user experience, the `MultiInvoker.sol` was developed to batch market actions & liquidity provisioning actions into a single transaction.&#x20;

For example, a new user wants to create a trade on one of Perennial's markets & pay a fee to the UI. Without the MultiInvoker following 4 transactions would be required:

1. `approve()` market #1 to transfer collateral
2. Request latest oracle price by calling `commitPrice()`
3. Make a trade on market #1 by calling `update()`&#x20;
4. Transfer fee to UI developer

Furthermore, every new market the user would interact with they'd need to `approve()` the collateral for that market. Now compare this with the MultiInvoker:

1. `approve()` MultiInvoker to transfer collateral (only required once)
2. Call `invoke()`:
   1. Request oracle via `commitPrice()`&#x20;
   2. Make trade via `update()`&#x20;
   3. Transfer fee to UI developer

## Example:

In order to your to improve development speed we’ve created an example repo which covers the basic calls you’ll need to populate a UI & submit trades.

Please email `info@perennial.finance` to be added to the repo.&#x20;

[^1]:


# Smart Contract Integrations

{% hint style="info" %}
You can find the deployed contract addresses here: [Contracts](/protocol-info/protocol-contracts)&#x20;
{% endhint %}

The following actions are useful when directly interacting with the markets. To make life easier, Perennial has built an [Operator](/building-on-perennial/before-integrating#operators) contract called: `MultiInvoker` which can be used to simplify/abstract much of this flow. See more about it [here](/building-on-perennial/frontend-and-client-integrations)

## Market Operations (Market.sol)

The following are common actions you might need to undertake to interact with an instance of a market contract.&#x20;

Source code: [here](https://github.com/equilibria-xyz/perennial-v2/blob/main/packages/perennial/contracts/Market.sol)

### Get a Market's Global Position

When interacting with a given market its useful to know the overall state. In order to find this you should call two functions: `position()` & `global()`. With these you can calculate things like open interest, skew, funding rate, interest rate etc.

* Call `position()`
  * Returns
    * `timestamp` - The timestamp of the position
    * `maker` - The maker position size\*
    * `long` - The long position size\*
    * `short` - The short position size\*
    * Notes
      * \* -  This is the **aggregate** value of all positions denominated in units of the [Payoff](/protocol/markets/payoff-and-positions) function
* Call `global()`&#x20;
  * Returns:
    * `pAccumulator` - The current PAccumulator state
    * `latestPrice` - The latest valid price

Helpful calculations:

* $$openInterestInUSD = (long + short) \* latestPrice$$
* $$marketSkew = long / short$$
* [Funding Rate](https://github.com/equilibria-xyz/perennial-interface-v2/blob/efc873819cc809c56010dc2feb7aff57cbb4e695/src/utils/fundingAndInterestUtils.ts#L38) - using `pAccumulator`&#x20;
* [Interest Rate](https://github.com/equilibria-xyz/perennial-interface-v2/blob/efc873819cc809c56010dc2feb7aff57cbb4e695/src/utils/fundingAndInterestUtils.ts#L8) - using `long` , `short` & `maker`

### Get an Account's Market Position

In order to read a particular account's position you can use the `positions()` function. This returns a similar object to the global `position()` call.&#x20;

* Call `positions(address)`
  * Returns
    * `timestamp` - The timestamp of the position
    * `maker` - The maker position size\*
    * `long` - The long position size\*
    * `short` - The short position size\*
    * `fee` - The fee for the position^
    * `keeper` - The fixed settlement fee for the position^
    * `collateral` - The collateral at the time of the position settlement^
    * `delta` - The change in collateral during this position^
  * Notes
    * \* The value of the position denominated in units of the [Payoff](/protocol/markets/payoff-and-positions) function
    * ^ Only used for pending positions

### Update Your Position (Make a Trade)

In each Market, there is an `update()` function which a user calls to modify their position. You can go long, short, make a market, deposit or withdraw collateral using this command.&#x20;

* `Approve()` DSU (collateral) on specific market
* Call `update()`
  * Arguments:
    * `account` - The account to operate on&#x20;
    * `newMaker` - The new maker position for the account\*
    * `newLong` - The new long position for the account\*
    * `newShort` - The new short position for the account\*
    * `collateral` - The collateral amount to add or remove from the account^
    * `protect` - Whether to put the account into a protected status for liquidations
  * Notes:
    * \* This is the **absolute** value of the position denominated in units of the [Payoff](/protocol/markets/payoff-and-positions) function.
    * ^ Positive number to add collateral, negative to remove.

### Calculating Available Liquidity:

When opening/closing a position the market is bound by available liquidity being provided by the Makers. In order to calculate this you can do the following:

* Call `position()`
  * Returns
    * `timestamp` - The timestamp of the position
    * `maker` - The maker position size\*
    * `long` - The long position size\*
    * `short` - The short position size\*
  * Notes
    * \* -  This is the **aggregate** value of all positions denominated in units of the [Payoff](/protocol/markets/payoff-and-positions) function
* Calculate Liquidity in USD
  * $$\begin{align\*}   liqMajor &= maker + \min(long, short) - \max(long, short) \  liqMinor &= liqMajor + maker  \end{align\*}$$&#x20;
    * *Note: availableMajor equal whichever side has more open interest*
* Call `global()`&#x20;
  * Returns:
    * `latestPrice` - The latest valid price
* Calculate Liquidity in units of Payoff&#x20;
  * $$liqUnits = liqMajor / latestPrice$$

### Confirming Position Update

Due to the delayed settlement flow of Perennial, while position updates are very likely to be settled there are rare cases where settlement might not occur. To check your position has been updated you can do the following:

* `Updated(account, context.currentTimestamp, ...)` is emitted when you submit an `updated()`.
* Call `Market.versions(timestamp)` using the timestamp from the event.
  * Returns a struct with the property `valid`. If the value is `true` then your update was successful.
  * If the value is `false`, you can check to see if the `timestamp` from the `Update()` event is after the `timestamp` returned in the `latest()` call in Market's Oracle. If this is the case, the `update()` has failed and needs to be resubmitted.&#x20;

## Example Contract Integration: Vaults

The multi-market maker vault that is featured on the Perennial UI is a great example of a contract integration into the Perennial market contracts.&#x20;

The vault is a standalone contract that acts as a normal user on configured markets. Whenever a user deposits into/withdraws from the vault contract it update the maker positions across the markets.&#x20;

See the codebase [here](https://github.com/equilibria-xyz/perennial-v2/blob/main/packages/perennial-vault/contracts/Vault.sol)

{% hint style="warning" %}
Make sure to check out the [Considerations](/building-on-perennial/before-integrating) section before building a direct integration!
{% endhint %}


# Offchain Infrastructure

To maintain composability the Perennial protocol is design to be fully operational with onchain transactions. However, abstractions of particular parts of the protocol have enabled usability enhancements for Takers and Makers alike. \
\
Here are some of examples of offchain infrastructure that works with Perennial:

### Keepers

Here are a list of services that receive a fee for certain functions related to the Perennial protocol:

1. [Oracle Keeper](https://github.com/equilibria-xyz/perennial-v2-keepers/blob/main/src/listeners/oracleListener/pythOracle.ts) - Responsible for committing requested price updates to the Oracles
2. [Liquidation Keeper](https://github.com/equilibria-xyz/perennial-v2-keepers/blob/main/src/listeners/marketListener/marketUserListener.ts) - Responsible for liquidating undercollateralized positions
3. [Order Keeper](https://github.com/equilibria-xyz/perennial-v2-keepers/blob/main/src/listeners/orderListener/orderListener.ts) - Responsible for executing executable orders
4. [Settlement Keeper](https://github.com/equilibria-xyz/perennial-v2-keepers/blob/main/src/listeners/settlementListener/settlementListener.ts) - Responsible for calling per-user settlement callbacks for position updates
5. [Intent Relayer](https://github.com/equilibria-xyz/perennial-v2-keepers/blob/main/src/relayer/index.ts) - Responsible for forwarding intents to `Controller.sol`. Sponsoring the transaction through Alchemy Account Abstraction

> NOTE: If you are running liquidator or order execution keepers, you can to deploy the BatchKeeper smart contract. This contract is responsible for batching transactions to reduce gas costs.&#x20;

### Intents API

With the 2.3 upgrade, Perennial supports [Intents](/protocol/intents). As signed messages they need a counterparty to execute these transactions. The Perennial protocol doesn't specify who or how these offchain messages are handled so it's up to market actors to design & implement a system.&#x20;


# Guides


# Creating a New Market

{% hint style="info" %}
**Currently Perennial has permissioned market creation.** However, in the future this will be opened up to anyone. Please join our discord to get the latest updates.
{% endhint %}

Perennial allows for permissionless market creation — anyone can come in and launch any market they desire. We anticipate there will be markets with long / short \<asset> payoffs for many types of assets, duplicate markets for assets that tweak LP/risk parameters, and many exotic defi-native markets.

Each market created in Perennial has a market operator controlled by an on-chain address (typically a multisig). The market operator serves a few functions:

* **Design & deploy the market** — pick market, choose price feed & utilization curve, launch market&#x20;
* **Set and tune parameters** — set initial parameters and adjust them in response to market **Manage**&#x20;
* **Market evolution** — upgrade the market, help with distribution to users, and more

In return, the market operator receives a portion of the fees collected by the market, creating an incentive for market creation.&#x20;

Because market operators have the ability to change important system parameters, we recommend that operator keys are managed by a multisig with a timelock (such that there is a delay before changes are implemented).&#x20;

Most markets will be operated by ecosystem participants — For the Long-SQTH pool, the market operator is Opyn team, and the key is controlled by Opyn protocol core multisig w/ timelock.&#x20;

Some markets will be protocol-owned — For the Long-ETH & Short-ETH markets, the Perennial protocol will be the market operator, and the key is initially controlled by Perennial's core multisig w/ timelock.&#x20;

## Initializing a Market

In order to create a market there are a number of parameters you need to consider. These will impact the operation & safety of the market. See the values explained below:

### Market Definition

#### **Tokens**

`token` is the underlying asset that the market settles in. It must match the quote currency of the oracle.

`reward` is the token that rewards are paid out in. It must not match the token. It may initially be set to the zero address, but once non-zero it may not be changed.

| Parameters                                                       | Invariants |
| ---------------------------------------------------------------- | ---------- |
| <ul><li><code>token</code></li><li><code>reward</code></li></ul> |            |

#### **Oracle**

`oracle` is the underlying oracle provider that feeds in the market’s underlying price.

`payoff` is the payoff provider that transforms the oracle’s underlying price to create the market’s price. The payoff may be set to the zero address to signify an identity function.

| Parameters                                                        | Invariants |
| ----------------------------------------------------------------- | ---------- |
| <ul><li><code>oracle</code></li><li><code>payoff</code></li></ul> |            |

**Roles**\
`coordinator` is allowed to update the risk parameters and claim any accrued risk fee.<br>

`beneficiary` is allowed to claim and accrued donation.

| Parameters                                                                  | Invariants |
| --------------------------------------------------------------------------- | ---------- |
| <ul><li><code>coordinator</code></li><li><code>beneficiary</code></li></ul> |            |

### Risk Parameters

Parameters per market, set by the risk coordinator.

#### **Position Fees**

`Skew` is a measure of when a markets Takers, long & short, aren't equal:

$$skew = \frac {long - short} {max(long, short)}$$

To derive the `TakerFee` we use the `Skew` we determine what the appropriate fee is when opening position fees:

$$taker fee = notional \* (    takerFee +    |skew’ - skew| \* takerSkewFee +     (|skew’| - |skew|) \* takerImpactFee )$$

Similarly, for the `MakersFee` in the market we calculate their fee based on the utilization of the present collateral:

$$maker fee = notional \* (    makerFee +    (utilization’ - utilization) \* makerImpactFee )$$

| Parameters                                                                                                                                                                      | Invariants                                                                                                                                                                                                                                                                                                                  |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>takerFee</code></li><li><code>takerSkewFee</code></li><li><code>takerImpactFee</code></li><li><code>makerFee</code></li><li><code>makerImpactFee</code></li></ul> | <ul><li><code>takerFee</code> <= protocolParameter.maxFee</li><li><code>takerSkewFee</code> <= protocolParameter.maxFee</li><li><code>takerImpactFee</code> <= protocolParameter.maxFee</li><li><code>makerFee</code> <= protocolParameter.maxFee</li><li><code>makerImpactFee</code> <= protocolParameter.maxFee</li></ul> |

#### **Collateralization**

An account is eligible for liquidation when:

$$collateral < max(     notional \* maintenance,     minMaintenance )$$

During a liquidation, the liquidator is eligible to take at most

$$liquidation fee = min(     max(         notional \* maintenance \* liquidationFee,         minLiquidationFee     ),     maxLiquidationFee )$$

Since oracle prices are only pushed upon request, account updates (position / collateral) are blocked when the market is stale:

$$oracle.currentTimestamp - oracle.latestTimetamp > staleAfter$$

If the market is stale a new price must be posted with the update in order to “freshen” it.

| Parameters                                                                                                                                                                                                                       | Invariants                                                                                                                                                                                                                                                                                                                                                                                                              |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>maintenance</code></li><li><code>minMaintenance</code></li><li><code>liquidationFee</code></li><li><code>minLiquidationFee</code></li><li><code>maxLiquidationFee</code></li><li><code>staleAfter</code></li></ul> | <ul><li><code>maintenance</code> >= protocolParameter.minMaintenance</li><li><code>minMaintenance</code> <= protocolParameter.maxAbsolutefee</li><li><code>liquidationFee</code> <= protocolParameter.maxCut</li><li><code>minLiquidationFee</code> <= protocolParameter.maxAbsolutefee</li><li><code>maxLiquidationFee</code> <= protocolParameter.maxAbsolutefee</li><li><code>staleAfter</code> <= 32 bits</li></ul> |

#### Limits

We define efficiency (the ratio of maximum taker notional over back maker notional) as:

$$efficiency =  maker / max(long, short)$$

The global position of the market must satisfy\*:

$$maker < makerLimit Efficiency > efficiencyLimit$$

*\* only applies when the position is increased*

| Parameters                                                                     | Invariants                                                                                                                   |
| ------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>makerLimit</code></li><li><code>efficiencyLimit</code></li></ul> | <ul><li><code>makerLimit</code> <= 48 bits</li><li><code>efficiencyLimit</code> >= protocolParameter.minEfficiency</li></ul> |

**Funding**

Funding is determined via a P-controller over long vs short skew.

$$
funding’ = min(     funding + (         ((skew’ + skew) / 2) \*         1 / pController.k \*         (t’ - t)     ),     pController.max )
$$

| Parameters                                                                        | Invariants                                                                                                                |
| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>pController.k</code></li><li><code>pController.max</code></li></ul> | <ul><li><code>pController.k</code> <= 48 bits</li><li><code>pController.max</code> <= protocolParameter.maxRate</li></ul> |

#### **Interest**

Incentivizes the delta-neutral capital costs of makers by deducting an interest rate from both long and short over a jump rate utilization curve.

U = JumpRate utilization curve

$$
\begin{align\*}  u &= \frac {\max(long, short)} {maker + \min(long, short)} \ Interest &= \min(maker, long + short) \* U(u)  \end{align\*}
$$

| Parameters                                                                                                                                                                                                     | Invariants                                                                                                                                                                                                                                                                                                                                           |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li>utilizationCurve.<code>minRate</code></li><li>utilizationCurve.<code>targetRate</code></li><li>utilizationCurve.<code>maxRate</code></li><li>utilizationCurve.<code>targetUtilization</code></li></ul> | <ul><li>utilizationCurve.<code>minRate</code> <= protocolParameter.<code>maxRate</code></li><li>utilizationCurve.<code>targetRate</code> <= protocolParameter.<code>maxRate</code></li><li>utilizationCurve.<code>maxRate</code>    <= protocolParameter.<code>maxRate</code></li><li>utilizationCurve.<code>targetUtilization</code> <= 1</li></ul> |

#### Miscellaneous

When `makerReceiveOnly` is active, the sign of the funding will instantaneously flip when the sign of the skew flips instead of gradually rebalancing through the P-controller. This is useful if we want to ensure that the makers always receive non-negative funding.

An amount of `virtualTaker` is added to both the long and short sides of the market for the purpose of funding and taker fee skew and impact calculations. This helps dampen fee volatility in new markets without a critical mass of activity.

| Parameters                                                                        | Invariants                                                                                   |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| <ul><li><code>makerReceiveOnly</code></li><li><code>virtualTaker</code></li></ul> | <ul><li><code>makerReceiveOnly</code></li><li><code>virtualTaker</code> <= 64 bits</li></ul> |

### Market Parameters

Parameters per market, set by the market factory owner.

#### Fees

`fundingFee`, `interestFee`, and `positionFee` are the percentages of the funding, interest, and maker / taker fees respectively that are collected as fees by the market.

The `settlementFee` is a fixed dollar-term amount that is collected to incentivize the oracle keeper any time a new oracle price is requested.

The pooled fees are split between the market and the protocol and market as follows:

$$
\begin{align\*}
protocol fee &= total fees \* protocolFee \\
market fee &= total fees - protocol fee
\end{align\*}
$$

The market fee is then further split as follows:

$$
\begin{align\*}
oracle fee &= market fee \* oracleFee + settlementFee \\
risk fee &= market fee \* riskFee
\end{align\*}
$$

With the oracle fee going to the oracle factory of the market, and the risk fee being claimable by the risk coordinator.

Any leftover market fees are recorded as a donation and given to the beneficiary to support any miscellaneous additional fees.

| Parameters                                                                                                                                                                                                 | Invariants                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>fundingFee</code></li><li><code>interestFee</code></li><li><code>positionFee</code></li><li><code>oracleFee</code></li><li><code>riskFee</code></li><li><code>settlementFee</code></li></ul> | <ul><li><code>fundingFee</code> <= protocolParameter.maxCut</li><li><code>interestFee</code> <= protocolParameter.maxCut</li><li><code>positionFee</code> <= protocolParameter.maxCut</li><li><code>oracleFee</code> + <code>riskFee</code> <= 1</li><li><code>settlementFee</code> <= protocolParameter.maxFeeAbsolute</li></ul> |

#### Pending Limits

Because of Perennial’s delayed-settlement system, there may be multiple pending positions that need to be settled during a market flywheel touch.

Since this is a loop, we want to limit the worst case gas consumption of this process by capping the number of pending positions in the market.

`maxPendingGlobal` limits the quantity of global pending positions, while `maxPendingLocal` limits the quantity of local pending positions per account.

Once hit, this limit will soft-pause the market until the keepers are able to catch up.

| Parameters                                                                           | Invariants                                                                                                 |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| <ul><li><code>maxPendingGlobal</code></li><li><code>maxPendingLocal</code></li></ul> | <ul><li><code>maxPendingGlobal</code> <= 16 bits</li><li><code>maxPendingLocal</code> <= 16 bits</li></ul> |

#### Incentives

Incentive rewards may be dripped to all three sides of the market at their individually specified rates per second:

* `makerRewardRate`
* `longRewardRate`
* `shortRewardRate`

The reward tokens are optimistically accrued meaning the market owner is responsible for ensuring the market contract has a suitable amount of reward tokens to satisfy outstanding accruals. There are no direct invariants to account for this.

| Parameters                                                                                                              | Invariants                                                                                                                                               |
| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>makerRewardRate</code></li><li><code>longRewardRate</code></li><li><code>shortRewardRate</code></li></ul> | <ul><li><code>makerRewardRate</code> <= 40 bits</li><li><code>longRewardRate</code> <= 40 bits</li><li><code>shortRewardRate</code> <= 40 bits</li></ul> |

#### Miscellaneous

When `takerCloseAlways` is active, long and short positions may always close even when their closure will bring the market into socialization. Likewise when `makerCloseAlways` is active, maker positions may always close even when their closure will bring the market into socialization. If inactive, for both cases, the closure will instead revert.

When `closed` is active, the market is in a closed-only state. No funding, interest, or profit & loss, or rewards are accrued, and positions may only be reduced. Liquidations and position fees are still active during this time.

| Parameters                                                                                                        | Invariants |
| ----------------------------------------------------------------------------------------------------------------- | ---------- |
| <ul><li><code>takerCloseAlways</code></li><li><code>makerCloseAlways</code></li><li><code>closed</code></li></ul> |            |

### Protocol Parameters

Protocol-wise parameters, set by the market factory owner.

#### Fee

`protocolFee` is the cut of the market fee that is taken by the protocol.

| Parameters                                 | Invariants                                |
| ------------------------------------------ | ----------------------------------------- |
| <ul><li><code>protocolFee</code></li></ul> | `protocolFee` <= protocolParameter.maxCut |

#### Parameter Limits

Limits apply to parameters in all instance markets as specified above.

| Parameters                                                                                                                                                                                                | Invariants                                                                                                                                                                                                                                                                  |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <ul><li><code>maxFee</code></li><li><code>maxFeeAbsolute</code></li><li><code>maxCut</code></li><li><code>maxRate</code></li><li><code>minMaintenance</code></li><li><code>minEfficiency</code></li></ul> | <ul><li><code>maxFee</code> <= 24 bits</li><li><code>maxFeeAbsolute</code> <= 48 bits</li><li><code>maxCut</code> <= 24 bits</li><li><code>maxRate</code> <= 32 bits</li><li><code>minMaintenance</code> <= 24 bits</li><li><code>minEfficiency</code> <= 24 bits</li></ul> |

<br>


# Subscribe to Market Updates

When applying trading strategies to markets you need to be able to know your exposure is at any given point in time.&#x20;

This guide will walk you through setting up a webhook to notify you of changes to Perennial's market & your positions. We'll use this Alchemy's Webhooks, Vercel & Perennial's SDK to achieve this.

## Workflow

The workflow for this system has three parts:

* Notification
* Process
* Action

### **Notification - Alchemy Webhooks**

Alchemy's Webhook service lets watch any topic or address on a number of different chains and POST the transaction data to any URL. This is useful for getting realtime changes to the Perennial's markets rather than going by a polling based approach.

In order to setup your webhooks you need to go your [Webhook Dashboard](https://dashboard.alchemy.com/webhooks):

Once there you can setup a new webhook for testing using the following Subgraph query:

```graphql
{
  block {
    logs(filter: {addresses: [], topics: ["0x29083474b417ce11b6e16e049302e231f5d3d753484fe3e8155ea0b7ffe4f3c1"]}) {
      data,
      topics,
      account {
        address
      }
    }
  }
}
```

Note: the topic for our&#x20;

Once you've entered the query, we need to get a URL to collect the data thats being sent. For development purposes the easiest method is to use Ngrok, a lightweight tunnel to your dev environment. After setting it up, paste the url into the URL section of the webhook.

### **Process - Vercel**

Now we have a service POST'ing data to an endpoint, we need to have a system to receive and process it. For this example we will use [Vercel](https://vercel.com) to host the endpoint, however any hosted environment will suffice.

Lets create a script at `/api/webhook.ts` to receive the webhook calls:

```typescript
"use server";

export async function POST(req: Request, res: Response) {
	const data = await req.json();
	const logs = data.event.data.block.logs

	// Loop all position updates
	logs.forEach((log) => {
		console.log('New Update: ', log)
	}

	return new Response({status: 200})
}
```

The script above takes data posted to the endpoint and logs it to the console.

To trigger it you need to modify the URL in the Alchemy Webhook page to match your Ngrok URL and click "Test". 9 times out of 10 this will do nothing.

In order to test, you need to specify which block to run your test on. Modify your Webhook's Subgraph to the following:

```graphql
{
	block (hash: "0x61dc23440d66afc1e2b1a73fb5c343a467ce0fc0bf4df57c319aba91884af622") {
    logs(filter: {addresses: ["0x61dc23440d66afc1e2b1a73fb5c343a467ce0fc0bf4df57c319aba91884af622"], topics: ["0x29083474b417ce11b6e16e049302e231f5d3d753484fe3e8155ea0b7ffe4f3c1"]}) {
      data,
      topics,
      account {
        address
      }
    }
  }
}
```

Pressing `Test` will trigger the webhook as the Subgraph has found a block with logs matching the topic. You should see the transaction's logs in your console.

Lets extend this a little further to make it relevant to your positions:

```typescript
"use server";

import {
ChainMarkets2,
fetchMarketSnapshots2
} from "perennial-sdk-ts";

// Constants
const bot_address = `0x29E9...E929`
const chainId = 421261 // Arbitrum

// Route handler
export async function POST(req: Request, res: Response) {
	const data = await req.json();
	const logs = data.event.data.block.logs;

	// Keep a track of updated markets
	const markets: string[] = [];
	
	// Loop all position updates
	logs.forEach((log) => {
		// Make a note of the market address
		const market = log.account.address;
		// Convert market address to token symbol
		const code = Object.entries(ChainMarkets2[chainId]).find(
			(x) => x[1].toLowerCase() === market.toLowerCase())?.[0];
		if (!markets.inlcudes(code)) markets.push(code);
	};

	// Fetch the latest state of your positions
	const positions = await fetchMarketSnapshots2(
		publicClient,
		bot_address,
		markets
	);
	console.log(positions)
	
	return new Response({status: 200})
}

```

The initial script has been modified to take note of the markets effected in the transaction that fired the webhook and then fetch a market position report for your wallet.

### Actions

Lets recap where we are:

* We have a service watching Perennial's markets & calling the endpoint when we position update is submitted.
* We have an endpoint which receives that data & checks which markets are being updated
* We have code that calculates your account's for the effected markets

From this point you can trigger code that modifies your position in reaction to the changes.

For some examples of how to get the most out of position data, see here :

* Check maker exposure & liquidation (if using leverage while making)
* Check exposure while in a vault
* Modify exposure - Increase leverage, reduce collateral etc.


# Perennial

## What is Perennial Finance?

**Protocol:**

Perennial is a DeFi-native derivatives primitive that allows for the creation of two-sided markets that trade exposure to an underlying price feed in a capital efficient manner.&#x20;

**App:**

Perennial.finance is one of the frontends for the Perennial protocol.

## How is Perennial different from other derivative protocols?

Perennial features a number of design decisions to keep it simple, modular and capital efficient:

* **USD Collateral** - Trades settled in USD, not volatile cryptocurrencies, this simplifies the protocol mechanism and improves resilience.
* **High Leverage** - Positions up to 50x are possible with the Perennial protocol.&#x20;
* **Position Netting** - Trades are matched against each other to ensure the protocol is capital efficient & that maker positions can cover larger trades.
* **Maker Vaults -** Makers can LP directly with the protocol or use a Vault. This simplifies LP for users unfamiliar with providing liquidity.&#x20;
* **Permissionless** — Permissionless market creation, integration, and composability.

## Does Perennial charge a platform fee?

Perennial has the option to apply a protocol level fee. However, at the moment the fee is 0 and there are no plans to increase it in the foreseeable future.

## Does Perennial have plans for a token?

At this time, Perennial doesn't have plans to release a token.&#x20;

## How can I contact the Perennial team?

You can message a team member on the Perennial [Discord server](https://discord.com/invite/n6ejatX5Rw) or email <info@perennial.finance>


# Trading

## Why can't I open a position?

There could be a few reasons that you aren't able to open a position:

**You already have an open position -** Perennial only allows one position per market. Please check you have no open positions for that market.&#x20;

**You don't have any collateral -** Make sure that you have added collateral in the protocol. You can check this by looking here:

<figure><img src="/files/fe0VlB8SwOravTzRcBV3" alt=""><figcaption></figcaption></figure>

**The market could be at 100% utilization -** The maker liquidity is fully utilized and no more positions can be opened. Check back later as full utilization incentivises new liquidity to be added to the Vaults.

## Why is the entry price different to when I clicked the "Place Trade" button?

The price you receive opening a position is the next oracle update, not when you click the button. The protocol is designed this way to stop bots from abusing timing inefficiencies amongst markets. \
\
On average the oracle should update every 10-15 seconds.&#x20;

## I reduced my position. Why didn't I get any USDC back?

When you decrease your position size, your collateral stays in the protocol. In order to withdraw it you need to click the "Withdraw Collateral" button and follow the instructions there.&#x20;

<figure><img src="/files/8Oe7qSXiiBQU8mp0wk7u" alt=""><figcaption></figcaption></figure>

## Why does my order show a "Pending" state?

When executing a trade, Perennial uses delayed settlement to ensure consistency in the market. When you submit your order it takes 1 oracle update to be entered into the system.&#x20;

To learn more about the Settlement flow see [here](/protocol/markets/oracles-and-settlement#settlement).

## Why do my trades keep failing when I use a Gnosis Safe?

Perennial V2 uses a request based oracle. When using a Gnosis Safe you must collect the signatures required to submit within roughly 1 minute to ensure the data isn't stale.

## I've had my position open for X minutes, why hasn't funding accrued?

Unlike CEXs, Perennials markets are updated each time someone updates their position within the market (open, close, make, etc). This means that the funding values (along with others) may appear to be stale. Don't worry the market will calculate the latest values on the next update. \
\
If you are unsure the you can check the UI to see what the unrealised values should be.&#x20;

## I love the charts on the app. What are you using?

*Charts are provided by TradingView, a platform for traders and investors with versatile research tools and market data to help track coins like* [*BTCUSD*](https://www.tradingview.com/symbols/BTCUSD/) *or* [*ETHUSD on charts*](https://www.tradingview.com/symbols/ETHUSD/) *and more*


# Markets

## Can you launch X market?

Perennial is constantly evaluating demand for different markets. Based on this & available liquidity, new markets will be launched. \
\
If you are interested in a particular market, please share it in the `Traders` channel on our Discord.

## When will vault capacity be increased?

Following the initial launch of V2, we expect vault capacities to be increased slowly as the new protocol spends further time in the market. \
\
This ensures the smooth operation of the protocol, by ensuring predicable  liquidity for traders and steady rates for makers.&#x20;

## Which vault should I deposit into?

Currently Perennial has two vault products: ETH Vault & BTC Vault. These vaults are based around providing to the ETH & BTC markets respectively.&#x20;

In addition to providing liquidity to their respective markets they also allocate a smaller portion of the deposited liquidity to other longer tail markets. This exposes the vault depositor to diversified set of markets, resulting in different LP charateristics.&#x20;

## What types of collateral can you deposit?

The protocol operates with purely stablecoin collateral. This means you can either deposit the USDC or DSU stablecoins to the protocol.\
\
Learn more about the protocol collateral [here](/protocol/markets/collateral).

## What is DSU?

DSU is akin to a stablecoin wrapper. It was chosen as the base collateral for Perennial as it reduces some of the undesirable characteristics of stablecoins & helps future proof the protocol.

See more about it [here](/protocol/markets/collateral).&#x20;


# Fees

## What are the fees charged by Perennial?

There are various fees in protocol. The exact amount charged depends on the market, the trade size etc. Perennial has engaged Gauntlet to help determine the best parameters for each market.&#x20;

Some of the fees are the following:

* Opening/Closing a Taker position
* Funding rate on open positions
* Opening/Closing a Maker position
* Interest rate on Idle capital

If you are interested to see the live fees on any market, check out the Market Information section in the UI:<br>

<figure><img src="/files/gbMSAplmRpKewbVAN8nv" alt=""><figcaption></figcaption></figure>

If you are interested in seeing all of the possible parameters, check out the [Market Creation](/building-on-perennial/guides/creating-a-new-market) section.

## How much does it cost to open a position on Perennial?

The fees are dynamically calculated when opening a position. Its based on position's impact on skew among other factors. You will be able to see a break down of the fees on when entering a position.&#x20;

## Why does fee change with position size?

Perennial aims to have a perfectly balanced Skew in every market. We achieve this by using a dynamic funding rate based on this parameter (See [Funding Rate](/protocol/markets/funding-and-interest-rate)).&#x20;

In addition, the protocol also charges a dynamic fee based on the impact your position would have on the market skew. The further the position pushes Skew up, the higher the fee. Conversely, when a position will reduce skew the fee is reduced.


# Markets & Vaults

List of markets, oracles & vaults governed by the Perennial Protocol

## **Arbitrum Network**

### **Markets:**

<table><thead><tr><th width="134">Market</th><th width="95">Ticker</th><th>Contract</th></tr></thead><tbody><tr><td>Ethereum</td><td>ETH</td><td><code>0x90A664846960AaFA2c164605Aebb8e9Ac338f9a0</code></td></tr><tr><td>Ethereum²</td><td>ETH²</td><td><code>0x004E1Abf70e4FF99BC572843B63a63a58FAa08FF</code></td></tr><tr><td>Bitcoin</td><td>BTC</td><td><code>0xcC83e3cDA48547e3c250a88C8D5E97089Fd28F60</code></td></tr><tr><td>Bitcoin²</td><td>BTC²</td><td><code>0x768a5909f0B6997efa56761A89344eA2BD5560fd</code></td></tr><tr><td>Solana</td><td>SOL</td><td><code>0x02258bE4ac91982dc1AF7a3D2C4F05bE6079C253</code></td></tr><tr><td>Polygon</td><td>MATIC</td><td><code>0x7e34B5cBc6427Bd53ECFAeFc9AC2Cad04e982f78</code></td></tr><tr><td>Arbitrum</td><td>ARB</td><td><code>0x3D1D603073b3CEAB5974Db5C54568058a9551cCC</code></td></tr><tr><td>Chainlink</td><td>LINK</td><td><code>0xD9c296A7Bee1c201B9f3531c7AC9c9310ef3b738</code></td></tr><tr><td>BNB</td><td>BNB</td><td><code>0x362c6bC2A4EA2033063bf20409A4c5E8C5754056</code></td></tr><tr><td>Celestia</td><td>TIA</td><td><code>0x2CD8651b0dB6bE605267fdd737C840442A96fAFE</code></td></tr><tr><td>Rollbit</td><td>RLB</td><td><code>0x708B750f9f5bD23E074a5a0A64EF542585906e85</code></td></tr><tr><td>Jupiter</td><td>JUP</td><td><code>0xbfa99F19a376F25968865983c41535fa368B28da</code></td></tr></tbody></table>

### Vaults

<table><thead><tr><th width="108.66666666666669">Name</th><th width="125">Assets</th><th>Contract</th></tr></thead><tbody><tr><td>Alpha</td><td>BTC, ETH</td><td><code>0xF8b6010FD6ba8F3E52c943A1473B1b1459a73094</code></td></tr><tr><td>Bravo</td><td>SOL, MATIC</td><td><code>0x699e37DfCEe5c6E4c5D0bC1C2FFbC2afEC55f6FB</code></td></tr></tbody></table>

***


# Protocol Contracts

List of deployed contracts & their addresses that make up the Protocol

{% hint style="info" %}
&#x20;For a list of Market Instances, check [here](/protocol-info/markets-and-vaults)
{% endhint %}

The following tables list the current protocol deployment for the Perennial protocol.

## Arbitrum

<table><thead><tr><th width="262">Contract</th><th>Address</th></tr></thead><tbody><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/AsterVault.json">AsterVault</a></td><td>0xF8b6010FD6ba8F3E52c943A1473B1b1459a73094</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/BegoniaVault.json">BegoniaVault</a></td><td>0x699e37DfCEe5c6E4c5D0bC1C2FFbC2afEC55f6FB</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MarketFactory.json">MarketFactory</a></td><td>0xDaD8A103473dfd47F90168A0E46766ed48e26EC7</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MarketFactoryImpl.json">MarketFactoryImpl</a></td><td>0xaD335343ea59e0d3eb8Ce91B95779C6647F10dde</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MarketImpl.json">MarketImpl</a></td><td>0xD5fbF1E37786a4507ec115BB35A938DdCbaE137d</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MarketParameterStorageLib.json">MarketParameterStorageLib</a></td><td>0x8a159CDB5FA8AF4A71f987F3Fb2D5229eC63c758</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MultiInvoker.json">MultiInvoker</a></td><td>0x431603567EcBb4aa1Ce5a4fdBe5554cAEa658832</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MultiInvokerImpl.json">MultiInvokerImpl</a></td><td>0xF56F08BBDDd53A2151BE08E32f43f91f657c9B4e</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/OracleFactory.json">OracleFactory</a></td><td>0x8CDa59615C993f925915D3eb4394BAdB3feEF413</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/OracleFactoryImpl.json">OracleFactoryImpl</a></td><td>0x19A4010E859ca3d10F0d928C6665F9a9E3BE4B22</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/OracleImpl.json">OracleImpl</a></td><td>0x0a47bb5E5260619204a578Bd477204FcE6246BB7</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PayoffFactoryImpl.json">PayoffFactoryImpl</a></td><td>0xf817521610600c4674364246A5CF4af8e627805D</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PayoffFactory.json">PayoffFactory</a></td><td>0xeea68DbE228210454D4443f4E1B37E842B848C3d</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/ProxyAdmin.json">ProxyAdmin</a></td><td>0x5bEA99BF18624AA504580546Ac9D9Ac3b9aeb747</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PythFactory.json">PythFactory</a></td><td>0x9F35B78c6502e2B19D45Dc275f24462B0fa577B4</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PythFactoryImpl.json">PythFactoryImpl</a></td><td>0x63DD4059971a9e24810A2Aea222460acA6687Bb6</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PythOracleImpl.json">PythOracleImpl</a></td><td>0x7A18A52EF9Ab4E2EDE9113ef13483eD18b395ca7</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/RiskParameterStorageLib.json">RiskParameterStorageLib</a></td><td>0xc24FeF7BB2f7AB454A3f982eD3b4B8268fF850BD</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/TimelockController.json">TimelockController</a></td><td>0xdA381aeD086f544BaC66e73C071E158374cc105B</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/VaultFactory.json">VaultFactory</a></td><td>0xad3565680aEcEe27A39249D8c2D55dAc79BE5Ad0</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/VaultFactoryImpl.json">VaultFactoryImpl</a></td><td>0xdECeC72B6beDe55ED2865A38346BF96Fcc3b4a8F</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/VaultImpl.json">Vault Implementation</a></td><td>0xD51013f4A3Bd69B108f84B1215d666fe96138d5C</td></tr></tbody></table>

### Arbitrum Payoff Helpers

<table><thead><tr><th width="180">Contract</th><th width="110.33333333333331">Unit</th><th>Address</th></tr></thead><tbody><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Giga.json">Giga</a></td><td><span class="math">x*10^9</span></td><td>0x7a98eFCe4A399794aE7524faEb2cc6A8eF730fCF</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Mega.json">Mega</a></td><td><span class="math">x*10^6</span></td><td>0xFfB33F838096cF3C3c7dD21c1F941BB2705248E1</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Kilo.json">Kilo</a></td><td><span class="math">x*10^3</span></td><td>0xDE7E2d1005Ea46a0e261E243F762Fc7Ca849ACAB</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Milli.json">Milli</a></td><td><span class="math">x/10^3</span></td><td>0xAE794C750991b19485E17788d1a19b83BA68bd62</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Micro.json">Micro</a></td><td><span class="math">x/10^6</span></td><td>0x4F7A6cCEd29712fc5B102E730C27324a01e74179</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/Nano.json">Nano</a></td><td><span class="math">x/10^9</span></td><td>0x1cc0E7883DC01cCa0CC7A04b1Eb3e51C290645E7</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/KiloPowerHalf.json">KiloPowerHalf</a></td><td><span class="math">\sqrt{x*10^3}</span></td><td>0x8Da96a2eDe1dd5Af8Bd3BD142226820f6Bb09751</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PowerHalf.json">PowerHalf</a></td><td><span class="math">\sqrt{x}</span></td><td>0x07B891ae5E0eeAF7FB407552C28EAc785Ac8AF9C</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MilliPowerHalf.json">MilliPowerHalf</a></td><td><span class="math">\sqrt{x/10^3}</span></td><td>0xbcA65Ce3629167600d52492b61A97627305F4E0e</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MegaPowerTwo.json">MegaPowerTwo</a></td><td><span class="math">x^2*10^6</span></td><td>0xe833e9bd294D9f1E1760BdC88C01C8deA4f0F7D7</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/KiloPowerTwo.json">KiloPowerTwo</a></td><td><span class="math">x^2*10^3</span></td><td>0xf94F18fe7eF42eee309eBFc287F2f425CB16cBc9</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/PowerTwo.json">PowerTwo</a></td><td><span class="math">x^2</span></td><td>0x6b1C4978142A9BC9dD5777866AA8Ad610deD696c</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MilliPowerTwo.json">MilliPowerTwo</a></td><td><span class="math">x^2/10^3</span></td><td>0x443cef645e29aE12C053f358b2875DF0B9A43166</td></tr><tr><td><a href="https://github.com/equilibria-xyz/perennial-v2/blob/56c3807bf5152efcfddf1eb1547a180817a8c2d2/packages/perennial-deploy/deployments/arbitrum/MicroPowerTwo.json">MicroPowerTwo</a></td><td><span class="math">x^2/10^6</span></td><td>0x18AD45bdda468259257E46BA07De6cD3d88Cd632</td></tr></tbody></table>


# Audits & Bug Bounty

### Audits

Perennial  v2 has had the following audits:

* [Zellic](https://github.com/equilibria-xyz/perennial-v2/blob/main/audits/0823%20-%20Perennial%20-%20Zellic%20Audit%20Report.pdf) (v2.0) - Full Audit
* [Sherlock](https://audits.sherlock.xyz/contests/106) (v2.0) - Full Audit Contest
* [Sherlock](https://audits.sherlock.xyz/contests/112) (v2.0) - Fix Review
* [Sherlock](https://audits.sherlock.xyz/contests/123) (v2.1) - Full Audit Contest
* [Sherlock](https://audits.sherlock.xyz/contests/254) (v2.2) - Full Audit Contest

### Insurance

Perennial contracts are actively secured by Sherlock insurance. \
[See the coverage agreement here](https://github.com/sherlock-protocol/sherlock-reports/blob/main/coverage-agreements/Perennial%20Coverage%20Agreement%202023.10.02.pdf)

### Bug Bounty

Perennial has a bugbounty program through Immunify, with bounties up to $500k. \
[See here for more info.](https://immunefi.com/bounty/perennial/)


# Introduction

### What is perp.fun?

**perp.fun is a simplified interface for trading perpetuals, built on top of the Perennial protocol.** It’s designed to strip the complexity out of trading — no cluttered interface, no limit orders, stop losses, or advanced settings. Just long or short bluechips with a few taps.

Your trades are routed through **Perennial’s purpose-built perps rollup**, giving you near-zero fees, fast execution, and full control at all times.

***

#### Features

* **Gasless trading** – Powered by Perennial’s rollup, there are no gas fees when placing trades.
* **BTC, ETH, SOL markets** – Trade up to 100x leverage on major bluechips.
* **Grow your flowers** – Each trade plants a seedling that blooms as your position thrives — or wilts when you’re close to liquidation.

***

#### Signups & Wallets

perp.fun uses embedded wallets via [**Privy**](https://www.privy.io/), so you can log in with X (Twitter), Discord, email, or a traditional wallet.

That means:

* You don’t need to connect a wallet up front — it’s created for you in the background.
* You’re still in full control of your account and funds.
* This is different from **app.perennial.finance**, which uses your connected wallet directly.

**How it works: perp.fun vs app.perennial.finance**

> **perp.fun** → Log in with X, Discord, wallet → Privy embedded wallet → Trades on Perennial protocol\
> **app.perennial.finance** → Connect wallet directly → Trades on Perennial protocol

***

#### Referrals

Every user gets a unique referral code. Share it with friends to earn **20% of the Petals** they generate through trading.\
Find your code in the top-right menu — copy the one auto-generated for you, or make your own.

***

#### Under the Hood

perp.fun runs entirely on top of the **Perennial protocol** — a custom-built rollup for perps, using an intent-based execution model with verified solvers and a derivatives AMM under the hood.\
Trades are gasless, settled instantly, and never require handing over custody.


# Installing Perp.fun

Add perp.fun to Your Phone’s Home Screen

For fast access and a native app-like experience, you can add [perp.fun](https://perp.fun) directly to your phone’s home screen. This guide walks you through how to do it on iOS (Safari) and Android (Chrome).

***

### iOS (Safari)

1. Open Safari

   Visit <https://perp.fun> in your Safari browser. *(Note: This only works in Safari on iOS.)*
2. Tap the Share Icon

   At the bottom of the screen, tap the share icon: ⤴️
3. Scroll & Select “Add to Home Screen”

   In the share menu, scroll until you see Add to Home Screen. Tap it.
4. Customize (Optional)

   You can rename the shortcut (e.g. perp.fun) if you like.
5. Tap Add

   The icon will now appear on your home screen like an app.

***

### Android (Chrome)

1. Open Chrome

   Navigate to <https://perp.fun> using the Chrome browser.
2. Tap the Menu Icon

   In the top-right corner, tap the 3-dot menu: ⋮
3. Select “Add to Home screen”

   Tap Add to Home screen from the dropdown menu.
4. Confirm

   You can edit the name (optional), then tap Add. Confirm the prompt.
5. Done

   The perp.fun shortcut will now be on your home screen, ready to launch like a native app.

***

#### Why Add It?

* ⚡ Lightning-fast access
* 🔒 Secure, same url every-time
* 📊 Optimized for trading on mobile

***

Need help? Jump into [Discord](https://discord.gg/perennial) for community support.


# Autopilot

Autopilot lets you copy the best traders on Perp.fun. \
\
You can select a user to copy and you'll follow their trades with your account. Whether their trading on single or multiple markets your account will follow their trades, pro-rated to your balance.  &#x20;

## How it Works

Every week the best traders from the week prior get the chance to become an Autopilot. These pilots can have up to 10 followers & will take home 10% of the positive PnL from their followers. So make sure to quickly follow if your favourite trader is selected!

Every open & close across Perp.fun's markets will be copied to your account. You can opt-out at any time but can opt-in only if there is space left!

It's easy to check in and see what your Pilot has been up to via the History tab. This page documents all the trades and PnL across them.&#x20;

## Copying a Pilot

{% hint style="warning" %}
When you start copying a Pilot, all of your current positions will be closed.&#x20;
{% endhint %}

To start copy a Pilot you can select them from the row at the top of the trade window:

<figure><img src="/files/DT5X3iV3rKiYXo6BkHtf" alt=""><figcaption></figcaption></figure>

You'll see a confirmation screen, showing information about Pilot, their PnL & current positions. If you're satisfied, click "Start Copying" and you'll begin to copy the trader.&#x20;

<figure><img src="/files/5Ws0x4Sjxq7Er9FUIqMC" alt=""><figcaption></figcaption></figure>

Once you've turned on Autopilot you'll be able to see the positions that you are copying and start to track the PnL of those positions.&#x20;

To see a history of the trades, you can click the bell icon. You'll see a list of your trades and the trades you've copied — marked "Autopilot".

{% hint style="info" %}
If your account doesn't meet the minimum balance requirements you'll skip your pilots trade!
{% endhint %}

## Becoming a Pilot

Apart from bragging rights, becoming an Autopilot means you get 10% profits from your copier's trades. So get your charts out and start making some positive PnL

To becoming a Pilot is a competitive process with a few simple requirements:

* Be one of the top 5 traders in the last 7 days.
* Minimum of 3 trades during the 7 days.&#x20;
* Pilots rotate every Monday at 1pm EST


