Skip to content

Commit

Permalink
feat: update readme (#164)
Browse files Browse the repository at this point in the history
This commit cleans up the readme
  • Loading branch information
marktoda committed Jul 7, 2023
1 parent acd24a6 commit e64c5fe
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 134 deletions.
71 changes: 32 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,54 @@
# What is UniswapX?
# UniswapX

[UniswapX](https://github.com/uniswap/UniswapX) is an off-chain order execution protocol meant to generalize token swaps across liquidity sources and provide price improvement for users. “Swappers” generate signed messages specifying the terms of their trade, in the form of a linear-decay Dutch order.
[![Integration Tests](https://github.com/Uniswap/uniswapx/actions/workflows/test-integration.yml/badge.svg)](https://github.com/Uniswap/uniswapx/actions/workflows/test-integration.yml)
[![Unit Tests](https://github.com/Uniswap/uniswapx/actions/workflows/test.yml/badge.svg)](https://github.com/Uniswap/uniswapx/actions/workflows/test.yml)

<p align="center">
<img width="575" alt="image" src="https://user-images.githubusercontent.com/8218221/216129758-df0ae2a3-05a7-44a2-bd79-0c7b1c10b8cb.png">
</p>
UniswapX is an intent-based ERC20 swap settlement protocol that provides swappers with a gasless experience, MEV protection, and access to arbitrary liquidity sources. Swappers generate signed orders which specify the intents of their swap, and fillers compete using arbitrary fill strategies to satisfy these orders.

“Fillers" read these orders and execute them, taking input assets from the swapper and fulfilling output assets. Fillers are entitled to keep any spread or profits they are able to generate by fulfilling orders. [Build a filler integration](integration_guide.md).

## UniswapX Order ***REMOVED***:
## UniswapX Protocol Architecture

To Swappers on the Uniswap front end, UniswapX orders look just like any other Uniswap order but behind the scenes they have a completely different flow.
<p align="center">
<img width="787" alt="image" src="https://user-images.githubusercontent.com/8218221/216479887-9f2ae4b3-9225-4ee3-86d4-797118082c88.png">
</p>
![Architecture](./assets/uniswapx-architecture.png)

1. A UniswapX order starts with a swapper on a Uniswap front end requesting a quote by entering two tokens and an input or output amount
2. That request is sent to UniswapX’s private network of RFQ Fillers who provide quotes for the proposed order. The best quote provided, is returned to the swapper on the Uniswap front end
3. The quote is transformed into a decaying Dutch Order by the Uniswap front end. It will decay over a preset number of blocks from the winning RFQ quote to Uniswap router price. If the swapper accepts the order they will sign it.
4. The signed order is first broadcast to the winner of the RFQ. They will have a set a number of blocks to fill at their winning bid price
5. If the RFQ winner fades, the signed order is then broadcast publicly. Any filler is then able to compete to fill the order at the given price in its decay curve.
### Reactors

## UniswapX Protocol Architecture:
Order Reactors _settle_ UniswapX orders. They are responsible for validating orders of a specific type, resolving them into inputs and outputs, and executing them against the filler's strategy, and verifying that the order was successfully fulfilled.

The UniswapX Protocol uses two types of contract, **Order Reactors** and **Order Executors,** to allow a network of Fillers to execute signed orders created through the Uniswap front end and signed via [Permit2](https://github.com/Uniswap/permit2):
Reactors process orders using the following steps:
- Validate the order
- Resolve the order into inputs and outputs
- Pull input tokens from the swapper to the fillContract using permit2 `permitWitnessTransferFrom` with the order as witness
- Call `reactorCallback` on the fillContract
- Verify that the output tokens were received by the output recipients

<p align="center">
<img width="850" alt="image" src="https://user-images.githubusercontent.com/8218221/216130577-e7f9263b-b5a7-463a-b082-6b8bc4d7d41c.png">
</p>
Reactors implement the [IReactor](./src/interfaces/IReactor.sol) interface which abstracts the specifics of the order specification. This allows for different reactor implementations with different order formats to be used with the same interface, allowing for shared infrastructure and easy extension by fillers.

**[Order Reactors](https://github.com/Uniswap/UniswapX/blob/main/src/interfaces/IReactor.sol)** are contracts that take in a specific type of order objects (like Dutch Orders), validate them, convert them to generic orders, and then execute them against a Filler’s Executor contract.
Current reactor implementations:
- [LimitOrderReactor](./src/reactors/LimitOrderReactor.sol): A reactor that settles simple static limit orders
- [DutchOrderReactor](./src/reactors/DutchOrderReactor.sol): A reactor that settles linear-decay dutch orders
- [ExclusiveDutchOrderReactor](./src/reactors/ExclusiveDutchOrderReactor.sol): A reactor that settles linear-decay dutch orders with a period of exclusivity before decay begins

The **[Dutch Order Reactor](https://github.com/Uniswap/UniswapX/blob/main/src/reactors/DutchOrderReactor.sol)** is Uniswaps Labs currently deployed reactor that allows execution of decaying Dutch Orders created through Uniswaps interface.
### Fill Contracts

**[Order Executors](https://github.com/Uniswap/UniswapX/blob/main/src/interfaces/IReactorCallback.sol)** (called **[ReactorCallback](https://github.com/Uniswap/UniswapX/blob/main/src/interfaces/IReactorCallback.sol))** are contracts created by fillers that defines their individual execution strategy which will be called by the reactor, in order to execute requested orders (you can find sample executor contracts [here](https://github.com/Uniswap/UniswapX/tree/main/src/sample-executors))
Order fillContracts _fill_ UniswapX orders. They specify the filler's strategy for fulfilling orders and are called by the reactor with `reactorCallback`.

# Integrating with UniswapX
See [Filler Integration Guide](integration_guide.md)
Some sample fillContract implementations are provided in this repository:
- [SwapRouter02Executor](./src/sample-executors/SwapRouter02Executor.sol): A fillContract that uses UniswapV2 and UniswapV3 via the SwapRouter02 router

# Helpful Links
### Direct Fill

| Name | Description | Link |
| --- | --- | --- |
| UniswapX Orders Endpoint | Publicly available endpoint for querying open UniswapX Orders | https://nwktw6mvek.execute-api.us-east-2.amazonaws.com/prod/api-docs |
| Order Creation UI | A test UI that allows you to create, sign and broadcast UniswapX orders. |https://interface-UniswapX.vercel.app/ |
| Permit2 | Uniswap’s permit protocol used by swappers to sign orders. | https://github.com/Uniswap/permit2 |
If a filler wants to fill orders using funds on-hand rather than a fillContract, they can do so gas efficiently using the `directFill` macro by specifying `address(1)` as the fillContract. This will pull tokens from the filler using `msg.sender` to satisfy the order outputs.

# Integrating with UniswapX
See [Filler Integration Guide](integration_guide.md)

# Deployment Addresses

| Contract | Address | Source |
| --- | --- | --- |
| Dutch Order Reactor | https://etherscan.io/address/0x81f570f48BE8d3D358404f257b5bDC4A88eefA50 | https://github.com/Uniswap/UniswapX/blob/main/src/reactors/DutchOrderReactor.sol |
| Permit2 | https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3 | https://github.com/Uniswap/permit2 |

| Contract | Address | Source |
| --- | --- | --- |
| Exclusive Dutch Order Reactor | [0xe80bF394d190851E215D5F67B67f8F5A52783F1E](https://etherscan.io/address/0xe80bF394d190851E215D5F67B67f8F5A52783F1E) | [ExclusiveDutchOrderReactor](https://github.com/Uniswap/UniswapX/blob/v1.0.0/src/reactors/ExclusiveDutchOrderReactor.sol) |
| OrderQuoter | [0x7714520f383C998e8822E8743FD6f90A2979689b](https://etherscan.io/address/0x7714520f383C998e8822E8743FD6f90A2979689b) | [OrderQuoter](https://github.com/Uniswap/UniswapX/blob/v1.0.0/src/OrderQuoter.sol) |
| Permit2 | [0x000000000022D473030F116dDEE9F6B43aC78BA3](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | [Permit2](https://github.com/Uniswap/permit2) |

# Usage

Expand All @@ -70,5 +65,3 @@ forge test
# run integration tests
FOUNDRY_PROFILE=integration forge test
```
# Disclaimer
This is EXPERIMENTAL, UNAUDITED code. Do not use in production.
Binary file removed assets/gouda-architecture.png
Binary file not shown.
Binary file added assets/uniswapx-architecture.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
99 changes: 4 additions & 95 deletions integration_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,118 +10,27 @@ The simplest fill strategy is called `Direct Filler`, where the trade is execute

```solidity
// Execute direct filler order
DutchOrderReactor.execute(order, address(1));
DutchOrderReactor.execute(order, address(1));
```

More sophisticated fillers can implement arbitrarily complex strategies by deploying their own Executor contracts. This contract should implement the [IReactorCallback](https://github.com/Uniswap/UniswapX/blob/main/src/interfaces/IReactorCallback.sol) interface, which takes in an order with input tokens and returns the allotted number of output tokens to the caller. To use an executor contract, fillers simply specify it’s address when calling `execute`:

```solidity
// Execute custom fill strategy
address executor = /* Address of deployed executor contract */ ;
bytes fillData = /* Call data to be sent to your executor contract */;
DutchOrderReactor.execute(order, executor, fillData);
bytes fillData = /* Call data to be sent to your executor contract */;
DutchOrderReactor.execute(order, executor, fillData);
```

For convenience, we’ve provided an [example Executor Contract](https://github.com/Uniswap/UniswapX/tree/main/src/sample-executors) which demonstrates how a filler could implement a strategy that executes a UniswapX order against a Uniswap V3 pool.

## 2. Retrieve & Execute Signed Orders

All signed orders created through the Uniswap UI will be available via the [UniswapX Orders Endpoint](https://***REMOVED***.execute-api.us-east-2.amazonaws.com/prod/api-docs). It’s up to the individual filler to architect their own systems for finding and executing profitable orders, but the basic flow is as follows:
All signed orders created through the Uniswap UI will be available via the [UniswapX Orders Endpoint](https://***REMOVED***.execute-api.us-east-2.amazonaws.com/prod/api-docs). It’s up to the individual filler to architect their own systems for finding and executing profitable orders, but the basic flow is as follows:

1. Call `GET` on the `prod/dutch-auction/orders` of the UniswapX Orders Endpoint to retrieve open signed orders
2. Decode returned orders using the [UniswapX SDK](https://github.com/Uniswap/UniswapX-sdk/#parsing-orders)
3. Determine which orders you would like to execute
4. Send a new transaction to the [execute](https://github.com/Uniswap/UniswapX/blob/a2025e3306312fc284a29daebdcabb88b50037c2/src/reactors/BaseReactor.sol#L29) or [executeBatch](https://github.com/Uniswap/UniswapX/blob/a2025e3306312fc284a29daebdcabb88b50037c2/src/reactors/BaseReactor.sol#L37) methods of the [Dutch Order Reactor](https://github.com/Uniswap/UniswapX/blob/main/src/reactors/DutchOrderReactor.sol) specifying the signed orders you’d like to fill and the address of your executor contract

If the order is valid, it will be competing against other fillers attempts to execute it in a gas auction. For this reason, we recommend submitting these transactions through a service like [Flashbots Protect](https://docs.flashbots.net/flashbots-protect/overview).

## 3. Enroll in UniswapX RFQ

The UniswapX RFQ system provides selected Fillers the opportunity to provide quotes to Uniswaps users in exchange for a few blocks of exclusive rights to fill UniswapX orders.

In this system, fillers will stand up a quote server that adheres to the UniswapX RFQ API Contract (below) and responds to requests with quotes. The RFQ participant who submits the best quote for a given order will receive exclusive rights to fill it using their Executor for the first few blocks of the auction.

### RFQ API Contract

To successfully receive and respond to UniswapX RFQ Quotes, Fillers should have a publicly accessible endpoint that receives quote requests and responds with quotes by implementing the following:

```jsx
method: POST
content-type: application/json
data: {
requestId: "string uuid - a unique identifier for this quote request",
tokenInChainId: "number - the `tokenIn` chainId",
tokenOutChainId: "number - the `tokenOut` chainId",
swapper: "string address - The swapper’s EOA address that will sign the order",
tokenIn: "string address - The ERC20 token that the swapper will provide",
tokenOut: "string address - The ERC20 token that the swapper will receive",
amount: "string number - If the trade type is exact input then this is amount of `tokenIn` the user wants to swap otherwise this is amount of tokenOut the user wants to receive",
type: "number - This is either `EXACT_INPUT` or `EXACT_OUTPUT`"
}
```

Response:

```jsx
{
chainId: "number - the chainId for the quoted token",
amountIn: "string number - If the request type is exact input then this field is `amount` from the quote request, otherwise this is the provided quote",
amountOut: "string number - If the request type is exact output then this field is `amount` from the quote request, otherwise this is the provided quote",
filler: "string address - The executor address that you would like to have last-look exclusivity for this order"

{ ...The following fields should be echoed from the quote request...},
requestId: "string uuid - a unique identifier for this quote request",
swapper: "string address - The swapper’s EOA address that will sign the order",
tokenIn: "string address - The ERC20 token that the swapper will provide",
tokenOut: "string address - The ERC20 token that the swapper will receive"
}
```

There is a latency requirement on responses from registered endpoints. Currently set to 0.5s, but will likely tweak during testing. If a filler receives a quote request they do not want to respond to they should send back an empty response with status code `204`.

Once this server is stood up and available, message your Uniswap Labs contact with its available URL to onboard it to UniswapX RFQ and start receiving quote requests.

### (Optional) Signed Order Webhook Notifications

Signed open orders can always be fetched via the UniswapX API, but to provide improved latency there is the option to register for webhook notifications. Fillers can register an endpoint with a filter, and receive notifications for every newly posted order that matches the filter.

**Filter**

Orders can be filtered by various fields, but most relevant here is `filler`. When registering your webhook notification endpoint, you must provide the `filler` address that you plan to use to execute orders and to receive the last-look exclusivity period.

**Notification**

Order notifications will be sent to the registered endpoint as http requests as follows:

```jsx
method: POST
content-type: application/json
data: {
orderHash: "the hash identifier for the order",
createdAt: "timestamp at which the order was posted",
signature: "the swapper signature to include with order execution",
swapper: "the swapper address",
orderStatus: "current order status (always should be `active` upon receiving notification)",
encodedOrder: "The abi-encoded order to include with order execution. This can be decoded using the UniswapX-SDK (https://github.com/uniswap/UniswapX-sdk) to verify order fields and signature",
chainId: "The chain ID that the order originates from and must be settled on",
filler?: "If this order was quoted by an RFQ participant then this will be their filler address",
quoteId?: "If this order was quoted by an RFQ participant then this will be the requestId from the quote request"
}
```

# Helpful Links

| Name | Description | Link |
| --- | --- | --- |
| UniswapX Orders Endpoint | Publicly available endpoint for querying open UniswapX Orders | https://***REMOVED***.execute-api.us-east-2.amazonaws.com/prod/api-docs |
| Order Creation UI | A test UI that allows you to create, sign and broadcast UniswapX orders. |https://interface-UniswapX.vercel.app/ |
| Permit2 | Uniswap’s permit protocol used by swappers to sign orders. | https://github.com/Uniswap/permit2 |



# Deployment Addresses

| Contract | Address | Source |
| --- | --- | --- |
| Dutch Order Reactor | https://etherscan.io/address/0xbd7f9d0239f81c94b728d827a87b9864972661ec | https://github.com/Uniswap/UniswapX/blob/main/src/reactors/DutchOrderReactor.sol |
| Permit2 | https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3 | https://github.com/Uniswap/permit2 |

0 comments on commit e64c5fe

Please sign in to comment.