Skip to content

Express Relay Docs #339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 55 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
ba754df
Initial commit
aditya520 Jun 11, 2024
bf983a1
added some framework to docs
aditya520 Jun 12, 2024
e758759
protocol guide wip
aditya520 Jun 12, 2024
52c3346
add intro express relay docs
anihamde Jun 12, 2024
8d46c78
Merge branch '(feat)-add-express-relay' of github.com:pyth-network/do…
anihamde Jun 12, 2024
8cb8c04
up - up - update
aditya520 Jun 13, 2024
0e4d456
updated guide
aditya520 Jun 24, 2024
f45490f
additional resources
aditya520 Jun 24, 2024
0a56469
tiny changes
aditya520 Jun 25, 2024
d524fd3
uhh
aditya520 Jun 25, 2024
73aca99
(WIP) Express relay docs
aditya520 Jun 25, 2024
27fbecc
(WIP) API refernce
aditya520 Jun 25, 2024
9cf9fec
(WIP) Express relay docs
aditya520 Jun 25, 2024
e1c5734
details around auction, opportunities, and permissioning
anihamde Jun 26, 2024
a1ebb8d
Merge branch '(feat)-add-express-relay' of github.com:pyth-network/do…
anihamde Jun 26, 2024
ce9082d
(WIP) Express relay docs
aditya520 Jun 26, 2024
d16b669
(WIP) Express relay docs
aditya520 Jun 27, 2024
ecb7ca6
add some moar content
anihamde Jun 28, 2024
a9d32cd
(WIP) Express relay docs
aditya520 Jun 28, 2024
f044075
content dump
anihamde Jun 28, 2024
b0df6fb
Merge branch '(feat)-add-express-relay' of github.com:pyth-network/do…
anihamde Jun 28, 2024
59b1992
Suggested edits (#360)
jayantk Jul 1, 2024
1780065
(WIP) Express relay docs- Yaser comments
aditya520 Jul 1, 2024
0ee5829
Update tables
m30m Jul 2, 2024
6ad0182
Change MEV definition from the old one
m30m Jul 2, 2024
703c905
added searcher guide to auction-server
anihamde Jul 2, 2024
31eb98f
finalize opportunity adapter docs dump
anihamde Jul 3, 2024
59227c3
Use cards for the main CTAs
m30m Jul 4, 2024
cf27a2e
Separate websocket api reference
m30m Jul 4, 2024
bc60b80
WIP-Searcher-guide
aditya520 Jul 4, 2024
9979e89
WIP-searcher-guide-refactor
aditya520 Jul 5, 2024
2bda439
wip
aditya520 Jul 5, 2024
c35641d
WIP-searcher-guide-refactor
aditya520 Jul 5, 2024
6901e48
Reorg searcher docs
m30m Jul 5, 2024
56d8802
WIP-protocol-guide-refactor
aditya520 Jul 5, 2024
4f2f9e4
WIP-searcher-guide-refactor
aditya520 Jul 5, 2024
d172628
WIP-ER
aditya520 Jul 8, 2024
e24d4b6
Update docs
m30m Jul 8, 2024
fb63c4e
some minor changes
anihamde Jul 9, 2024
47ea3f0
WIP-searcher-guide-refactor
aditya520 Jul 9, 2024
84d8831
WIP-searcher-guide-refactor
aditya520 Jul 9, 2024
078f9f0
WIP-searcher-guide-refactor
aditya520 Jul 9, 2024
d3263cc
WIP-comments-resolved
aditya520 Jul 9, 2024
d816fed
address change
aditya520 Jul 9, 2024
d028c8d
WIP-comments-resolved
aditya520 Jul 10, 2024
2448bc8
WIP-comments-resolved
aditya520 Jul 10, 2024
a842125
few small fixes pt 1
anihamde Jul 10, 2024
04826af
WIP-intro page
aditya520 Jul 10, 2024
5d3e43e
few small fixes pt 2
anihamde Jul 10, 2024
c9963d9
Merge branch '(feat)-add-express-relay' of github.com:pyth-network/do…
anihamde Jul 10, 2024
1338c14
wip docs
aditya520 Jul 10, 2024
c97754c
Express Relay docs v1
aditya520 Jul 10, 2024
78cb484
index change
aditya520 Jul 11, 2024
59459ce
Changed example reference to example repo
aditya520 Jul 11, 2024
dee1c14
Express Relay v1.xx
aditya520 Jul 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions images/express_relay/express_relay_schematic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions pages/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@
"type": "page"
},

"express-relay": {
"title": "Express Relay",
"type": "page"
},

"get-in-touch": {
"title": "Get In Touch ↗",
"type": "page",
Expand Down
39 changes: 39 additions & 0 deletions pages/express-relay/_meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"documentation-home": {
"title": "← Documentation Home",
"href": "/home"
},

"-- Express Relay": {
"title": "Express Relay",
"type": "separator"
},
"index": "Introduction",

"-- How-to Guides": {
"title": "How-To Guides",
"type": "separator"
},

"integrate-as-protocol": "Integrate as a Protocol",
"integrate-as-searcher": "Integrate as a Searcher",

"-- Reference Material": {
"title": "Reference Material",
"type": "separator"
},

"api-reference": "API Reference",
"contract-addresses": "Contract Addresses",
"error-codes": "Error Codes",

"examples": {
"title": "Example Application ↗"
},
"-- Understand Express Relay": {
"title": "Understanding Express Relay",
"type": "separator"
},

"how-express-relay-works": "How Express Relay Works"
}
3 changes: 3 additions & 0 deletions pages/express-relay/api-reference.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# API Reference

Link to swagger
1 change: 1 addition & 0 deletions pages/express-relay/contract-addresses.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Contract Address
Empty file.
1 change: 1 addition & 0 deletions pages/express-relay/how-express-relay-works.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Design Overview
9 changes: 9 additions & 0 deletions pages/express-relay/how-express-relay-works/auction.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
The auction in Express Relay is held off-chain at the auction server. Bids arrive at the auction server and compete against other bids vying for the same permission key. A relayer selected by governance serves as the auctioneer and is expected to determine the auction in line with the criterion of maximizing the revenue shared back to the protocol that generated this opportunity. That means the auctioneer is expected to forward the subset of bids that maximizes the revenue back to the protocol.

Thus, the Express Relay auction is analogous to a sealed-bid auction, in that participants in the auction will not have the contents of their bid disclosed publicly unless they are forwarded on-chain. Generally, bids are forwarded on-chain if they are expected to execute successfully on-chain, though additional "fallback" bids may be forwarded as well in case of execution failures for the expected winners. The `ExpressRelay` contract extracts the payment of the specified bid amount only if the searcher's bid executes successfully on-chain. Hence, the Express Relay auction can be seen as a generalization of a [first-price sealed-bid auction](https://en.wikipedia.org/wiki/First-price_sealed-bid_auction), in that multiple bids can win and pay their first price.

The revenue from the auction is shared amongst relevant stakeholders in the Express Relay system. This includes:
- the protocol, which generated the relevant opportunity
- the relayer, which handled running the off-chain components of the system

The exact revenue splits can be found in the Express Relay read contract and are subject to ...
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a page of Example Application. We can use that to explain if needed.

Empty file.
11 changes: 11 additions & 0 deletions pages/express-relay/how-express-relay-works/opportunities.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
In the context of Express Relay, an opportunity refers to a potential transaction that a searcher can execute on a protocol. Typically, the term "opportunity" is used for such transactions that are lucrative and therefore hotly contested by many searchers.

In the pre-Express Relay world, opportunities therefore correspond to MEV: a protocol generates MEV when an opportunity appears on that protocol and searchers bid up the right to execute the opportunity at the validator level.

In the context of Express Relay, the value deriving from an opportunity no longer flows to the validator but instead is recaptured by the system and shared back with the protocol. In Express Relay, protocols expose opportunities to the network of integrated searchers, and the searchers then bid on priority to execute those opportunities. Critically, the auction has moved from being determined by validators to a lower level at the protocol level.

Explain Opportunity Adapter contract

Brief explanation of and Links to permit2/create2/factory

Explanation of how to write the monitor at a high level
17 changes: 17 additions & 0 deletions pages/express-relay/how-express-relay-works/permissioning.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
`permissionId` is a `bytes` object that represents the unique identifying information of a position within the protocol. `permissionId` allows the system to distinguish between bids competing on different opportunities and thereby run more scoped and efficient auctions.

For some protocols, each borrower has a unique position, so the borrower address uniquely identifies a position. For other protocols, each borrower might have multiple positions, distinguished by the address of the collateral asset or by a uint256 id number. In those cases, the set of information that uniquely identifies a position would include multiple fields.

`permissionId` is the concatenation of all these fields in bytes format. To concatenate these fields together, you can call `abi.encode()`. For example, if a protocol featured a unique position per borrower, then it could form `permissionId` as

```
bytes memory permissionId = abi.encode(borrowerAddress);
```

On the other hand, if a protocol allowed a borrower to open as many new positions as they wanted, denoted by an identifier `uint256 positionId`, then it could form permissionId as

```
bytes memory permissionId = abi.encode(borrowerAddress, positionId);
```

The `permissionId` is used in the `ExpressRelay` contract to toggle permissions for interacting with the protocol. This toggling is checked within the protocol's code to ensure that the current transaction is within the context of Express Relay, so that recaptured value can be returned to the protocol.
Empty file.
32 changes: 32 additions & 0 deletions pages/express-relay/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Introduction

Many protocols generate MEV on a regular basis. Borrow-lending protocols for example expose lucrative liquidation bonuses that searchers compete for on tips made to the chain's miners or validators. Most of the value in the liquidation opportunity is captured by the validators, so the liquidation bonus is in essence a transfer of wealth from the protocol to the validators.

Express Relay enables protocols to recapture the MEV they currently leak to validators. By integrating with Express Relay, a protocol internalizes the auction for priority on its lucrative transactions (e.g. liquidations). It also taps into an existing set of searchers already integrated into and actively performing liquidations through Express Relay, reducing the need for the protocol to boostrap and maintain or incentivize its own set of liquidators.

![](images/express_relay/express_relay_schematic.svg)

## What is Express Relay?

### How does Express Relay work?

Express Relay features an off-chain auction (run by a third-party entity, the "relayer") where searchers bid on priority rights to transact on a protocol position or opportunity. Once an auction is concluded, the relayer will forward the winning parties' transactions onto the blockchain, where they will pass through the Express Relay entrypoint smart contract before being processed at the end protocol. The entrypoint contract handles permissioning and disbursement of fees to the relevant entities in the system.

### Different types of actors in Express Relay

There are four imporant agents in the Express Relay pipeline:

- Relayer: runs the off-chain auction according to an agreement with the Pyth DAO and forwards winning transactions onto the blockchain
- Protocol DAO/owner: integrates protocol with Express Relay in order to recapture leaked MEV, which can then be shared with protocol stakeholders
- Searcher: participates in the Express Relay auction to capture value from lucrative opportunities such as liquidation bonuses
- Pyth DAO: owner and governing authority of the Express Relay system, designates the relayer to run the off-chain components of the system

### Which protocols can integrate with Express Relay?

Protocols that currently leak MEV to validators because the validators control the ordering of lucrative transactions on the protocol can integrate with Express Relay. By doing so, such a protocol internalizes control over the ordering of these lucrative transactions, which means it does not need to surrender value to the validators.

Apart from recapturing MEV, protocols that are in need of a stable set of searchers that can p . Integrating with Express Relay gives a protocol access to the robust searcher network already active in the Express Relay ecosystem. This means

Lending, perps, and derivatives protocols that use liquidations are an obvious source of MEV and could benefit from integration with Express Relay. In addition,

## Links to other pages
219 changes: 219 additions & 0 deletions pages/express-relay/integrate-as-protocol.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
import { Callout, Tabs, Steps } from 'nextra/components'

# How to Integrate Express Relay as a Protocol

Protocol developers can **permissionlessly** integrate with Express Relay to recapture MEV and access a network of searchers.

Integrating with Express Relay involves two main steps:

- Update the Protocol's contract to **permission** Express Relay transactions.
- Write a script to **expose** liquidation opportunities to Searchers for auction.

## Update the Protocol's Contract

The Protocol's contract must permit Express Relay to access liquidation opportunities.

<Steps>
### Install the Express Relay SDK

Pyth provides a [Solidity SDK](https://www.npmjs.com/package/@pythnetwork/express-relay-sdk-solidity) to help developers integrate Express Relay into your Protocol.
The SDK exposes [`IExpressRelay`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol) and [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol) interfaces to interact with Express Relay.

<Tabs items={['Hardhat', 'Foundry']}>
<Tabs.Tab>
If you are using Hardhat, you can install the SDK using npm:

```bash copy
npm install @pythnetwork/express-relay-sdk-solidity
```
</Tabs.Tab>
<Tabs.Tab>
If you are using Foundry, you must create an NPM project if you don't already have one. From the root directory of your project, run:

```bash copy
npm init -y
npm install @pythnetwork/express-relay-sdk-solidity
```

Then add the following line to `remappings.txt` file:

```text copy
@pythnetwork/express-relay-sdk-solidity/=node_modules/@pythnetwork/express-relay-sdk-solidity
```
</Tabs.Tab>
</Tabs>

### Modifying the Protocol's Contract

Developers need to update the Protocol's contract to:

1. Utilize [`isPermissioned`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelay.sol#L10C14-L10C28) method from `IExpressRelay` interface to **permit** Express Relay transactions.
1. Implement the [`IExpressRelayFeeReceiver`](https://github.com/pyth-network/pyth-crosschain/blob/main/express_relay/sdk/solidity/IExpressRelayFeeReceiver.sol#L4) interface to **receive** funds from Express Relay.

#### 1. Permit Express Relay Transactions

The `isPermissioned` function takes two arguments:
1. `protocolFeeReceiver`: The address of the Protocol's contract.
1. `permissionId`: A unique identifier for the liquidation opportunity.

<Callout type="info" emoji="ℹ️">
The `permissionId` allows you to permission an depermission a set of transaction. ........ To know more about permission ID, refer to the [Permission ID](#) page.
</Callout>

```solidity copy
import "@pythnetwork/express-relay-sdk-solidity/IExpressRelay.sol";

// Express Relay contract address on Optimism Sepolia
// Check {INSERT CONTRACT ADDRESS PAGE LINK} for the address deployed on other networks
address expressRelay = 0xD6e417287b875A3932c1Ff5dcB26D4D2C8b90B40;

require(
IExpressRelay(expressRelay).isPermissioned(
protocolFeeReceiver,
permissionId
),
"invalid liquidation"
);
```


#### 2. Set up Fee Receiver

The `IExpressRelayFeeReceiver` interface requires the Protocol's contract to implement the `receiveAuctionProceedings` function. The Express Relay server calls this function to send funds to the protocol's contract.

```solidity copy
interface IExpressRelayFeeReceiver {
function receiveAuctionProceedings(
bytes calldata permissionKey
) external payable;
}
```






The following code snippet shows a sample liquidation method and updates to the Protocol's contract to permit Express Relay transactions:

```solidity showLineNumbers {1,2,12,14,39-43, 59-63} copy
import "@pythnetwork/express-relay-sdk-solidity/IExpressRelay.sol";
import "@pythnetwork/express-relay-sdk-solidity/IExpressRelayFeeReceiver.sol";

struct Vault {
address tokenCollateral;
address tokenDebt;
uint256 amountCollateral;
uint256 amountDebt;
uint256 minHealthRatio;
}

contract EasyLend is IExpressRelayFeeReceiver {

address public immutable expressRelay;

constructor(
address expressRelayAddress,
address oracleAddress,
bool allowUndercollateralized
){
_nVaults = 0;
expressRelay = expressRelayAddress;
_oracle = oracleAddress;
_allowUndercollateralized = allowUndercollateralized;
}

/**
* @notice liquidate function - liquidates a vault
* @param vaultID: ID of the vault to be liquidated
*/
function liquidate(uint256 vaultID) public {
Vault memory vault = _vaults[vaultID];
uint256 vaultHealth = _getVaultHealth(vault);
// Proceed only if the vault health is below the minimum health ratio
if (vaultHealth >= vault.minHealthRatio) {
revert InvalidLiquidation();
}

// Check if the liquidation is permissioned
bool permissioned = IExpressRelay(payable(expressRelay)).isPermissioned(
address(this),
abi.encode(vaultID) // vault id uniquely represents the opportunity and can be used as permission id
);
require(permissioned, "invalid liquidation");

IERC20(vault.tokenDebt).transferFrom(msg.sender,address(this),vault.amountDebt);
IERC20(vault.tokenCollateral).transfer(msg.sender,vault.amountCollateral);

_vaults[vaultID].amountCollateral = 0;
_vaults[vaultID].amountDebt = 0;
}

/**
* @notice receiveAuctionProceedings function - receives the native token from the express relay
* You can use the permission key to distribute the received funds to users who got liquidated, LPs, etc...
*
* @param permissionKey: permission key that was used for the auction
*/
function receiveAuctionProceedings(
bytes calldata permissionKey
) external payable {
emit VaultReceivedETH(msg.sender, msg.value, permissionKey);
}

}
```
</Steps>


## Expose Liquidation Opportunities to Searchers

Protocols must fetch liquidation opportunities like vaults and positions eligible for liquidation and expose them to Express Relay for auction.

The Express Relay auction server provides a **POST** method, `/v1/opportunities`, which accepts a JSON payload containing the details of the liquidation opportunity.

The JSON payload should contain liquidation opportunities in the following format:

```json
{
"target_calldata": "0xdeadbeef", // Calldata to perform liquidation
"chain_id": "op_sepolia",
"target_contract": "0xcA11bde05977b3631167028862bE2a173976CA11", // Protocol contract address to call for liquidation
"permission_key": "0xcafebabe", // Unique identifier for the liquidation opportunity
"target_call_value": "1", // Value(in Wei) to send with to the Protocol contract.
"buy_tokens": [ // Tokens to buy (Collateral)
{
"amount": "1000",
"token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
],
"sell_tokens": [ // Tokens to sell (Oustadaing Debt)
{
"amount": "900",
"token": "0x2260fac5e5542a773aa44fbcfedf7c193bc2c599"
}
],
"version": "v1" // Opportunity format version
}
```

TODO: Include a callout to give more info about permission ID

Protocols must evaluate each position's health using the latest Oracle prices before exposing them to Express Relay.
You can do this by indexing the chain, listening to protocol events, or querying open positions through an RPC provider.



## Additional Resources

You may find these additional resources helpful for integrating Express Relay as a protocol.

### Example Application

[Easy Lend](https://github.com/pyth-network/pyth-crosschain/tree/main/express_relay/examples/easy_lend) is a simple lending protocol that allows users to borrow and lend assets. This lending protocol contract is updated to permit Express Relay transactions.

### Contract Address

### Error Codes

### API Reference
4 changes: 4 additions & 0 deletions pages/express-relay/integrate-as-searcher.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# How to Integrate Express Relay as a Searcher

This guide explains how to integrate Express Relay as a searcher for liquidation opportunities.
To integrate Express Relay as a searcher, you need to:
5 changes: 5 additions & 0 deletions pages/home/_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"href": "/entropy"
},

"Express Relay": {
"title": "Express Relay →",
"href": "/express-relay"
},

"--- Additional Information": {
"title": "Additional Information",
"type": "separator"
Expand Down
1 change: 1 addition & 0 deletions pages/home/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Pyth Network offers several products for developers:
Aptos, Sui, NEAR, and several Cosmos chains.
- [Benchmarks](../benchmarks) provides historical Pyth prices for both on- and off-chain use.
- [Entropy](../entropy) allows developers to generate secure random numbers on the blockchain.
- [Express Relay](../express-relay/) enables protocols to eliminate their MEV while gaining access to active searchers and liquidators.

Please follow the links above to learn about each product and how to integrate them into your application.

Expand Down