- Published on
A truly permissionless RFQ
- Authors
- Name
- merkle
- @merkle_mev
The merkle private mempool generates revenue by arbitraging away inefficient trades. We believe the natural next step is to build a system that minimize the MEV as much as possible, or uses it to provide better quotes to traders.
We settled on a intent-based RFQ system that is fully permission-less, portable to any chain, and can be used by any wallet or dapp. It's a mix between a CLOB and a AMM, and it's powered by MEV. Intent systems have downsides, but if used right, they can be extremely powerful.
Introduction
merkle is a MEV-focused company building a suite of products to minimize the impact of MEV on the Ethereum network. We believe that MEV is a natural consequence of the way AMM work, and that it can be used to provide better quotes to traders.
Onchain RFQ systems are great for a few reasons:
- Offchain liquidity leverage: For the main assets (BTC, ETH, USD), most of the liquidity is offchain.
- Onchain breath of assets: Any onchain asset can be traded.
- Auction: The auction style guarantees (with > 3 bidders) that prices are optimal (as close as possible to true market price).
We set out to build the next generation of onchain trading, powered by RFQ and MEV. Most RFQ systems today choose to let fillers make transactions and are geared mostly towards offchain liquidity. They require an allowlist and run on a variety of assumptions about fillers.
Our initial goals were the following:
- A gas free RFQ system: We wanted a system that abstract away gas for the user.
- A simple API: The API should be dead simple and fully permissionless for both traders and fillers.
- MEV protection: MEV is at the heart of everything we do, therefore we understand how crucial minimizing the impact of MEV on the network is.
- Programmable Privacy: Revealing your trades in advance can negatively impact the quotes.
- Fast: Swaps should be fast, and the system should be able to handle high throughput.
- Bribes: We wanted to allow swappers to bribe validators for faster inclusion (on Ethereum).
In the near future, merkle RFQ will be embedded into our merkle Ethereum Builder, providing block-level price discovery.
Architecture
Traders post orders of two types to our RFQ:
For developers, read our docs
minimize_in
: The trader is looking for a final output and wants to minimize the input of the trade.maximize_out
: The trader wants to trade a set quantity for the maximum possible of the output asset.
In addition, traders can set a minimum they are willing to accept (maximize_out
) and and maximum they are willing to pay (minimize_in
).
Fillers listen to incoming orders on a public websocket and respond with a bid. A bid is built with 2 parameters:
- A searcher contract: The onchain contract filling the order.
- A searcher calldata: The calldata to pass to the searcher contract.
Example of a basic taker contract:
contract MyContract {
// this callback is called by the Merkle order settler,
// at this point, your taker contract already has the input
// amount.
function take(Order memory _order, uint256 minPayment, bytes calldata data) external returns (bool) {
// make sure merkle is calling it
require(msg.sender == "0xfDEd04Ad91903c20a17eB4A1409C5eBF6EFE4E8A", "UNAUTHORIZED")
// .... DO YOUR MAGIC / SWAP TOKENS etc. ......
(uint256 amountOut, ERC20 tokenOut) = (_order.amountOut, ERC20(_order.tokenOut));
// transfer output tokens to settler
tokenOut.transfer(msg.sender, amountOut);
// transfer payment to the settler contract,
// or use prepaid gas
address payable caller = payable(msg.sender);
caller.transfer(minPayment);
// if it's a "minimizeInput" order, make sure to return the input
// that isn't used back to the settler contract
_order.tokenIn.transfer(msg.sender, _order.tokenIn.balance(address(this)))
return true;
}
}
merkle simulates all bids to figure out their value. The system is built such that fillers can simulates their own bid easily using a simple eth_call
(See documentation).
// contract address: 0xfDEd04Ad91903c20a17eB4A1409C5eBF6EFE4E8A
// set from: 0x0 to bypass signature check on the order
function simulate(
Order memory _order,
address _taker, // this should be the address of your taker contract
bytes calldata _takerData, // this will be passed as callback data
) public returns (uint256 tokenInAmount, uint256 tokenOutAmount, uint256 minPayment);
Swap UI
merkle RFQ comes with a custom built, fully permission-less UI. The UI is built to be simple, yet complete.
Call for solvers
Currently, merkle RFQ is not production ready as there are no solvers competing for orderflow. We will be routing our own orderflow through the RFQ in the coming weeks, and we are looking for solvers to fill it. Get in touch with us on Telegram or Discord for help getting started. No account necessary.