- Published on
Off-Chain Bundles
- Authors
- Name
- merkle
- @merkle_mev
Today we are excited to announce a new idea we have been working on at Merkle as a feature of our block builder!
One of the biggest challenges with developing on Ethereum is the cost of gas to execute smart contracts. Searchers compete in the bundle auction by minimizing their gas footprint through various gas optimization techniques. Most searchers construct their bundles locally on simulated state to pass the exact minimal input to their bot contract required to carry out their MEV opportunity. Often times this contract is written to do as little work on-chain as possible. Competing in common MEV opportunities today is extremely difficult due to the level sophistication and development resources necessary.
Some strategies such as blind arbitrage for backrunning MEV Share transactions pose a significant difficulty. Since the transaction is protected, information about the pools the transaction interacts with and how much volume it is swapping is not always visible. Therefore searcher bots must implement the optimal calculations for their own swaps in the smart contract itself rather than locally. Computation for this logic as well as executing the MEV swaps or transfers greatly increases the gas cost of the bundle, leaving less profit for the searcher.
What if there was a way to move all non-critical compute required by a bundle off-chain and only pay for the gas required for the critical compute on-chain? Welcome to off-chain bundles!
Off-Chain Bundles
The goal is to allow searchers to submit a bundle with MEV transactions consisting of two parts, off-chain compute and on-chain settlement. The MEV bot transaction submitted in the bundle is the off-chain compute. Merkleās block builder will simulate this off-chain transaction at the bundleās inclusion index of the current block. The return data is then used to construct the on-chain settlement transaction that acts as the final MEV bot transaction. The exact spec of this feature is described in more detail below. This allows searchers to implement arbitrary logic in the the initial off-chain transaction with control over the precise execution of the on-chain transaction that will be included in the block to minimize gas footprint.
API (eth_sendBundle)
We have introduced an extenstion to the eth_sendBundle API endpoint for off-chain bundles. As seen below, it is very similar to the existing eth_sendBundle API endpoint but includes a new object for off-chain transactions which includes the to, code, data, offChainGasLimit and gasLimit fields.
{
"type": "eth_sendBundle",
"params": [
{
"txs": [
"0x...", // mempool tx
"0x...", // mempool tx
{ // off-chain tx
"to": "0x...", // searcher bot contract address
"gasOffChainLimit": "0x...", // gas limit for off-chain transaction
"gasLimit": "0x...", // gas limit for on-chain transaction
"data": "<calls the search() function with some parameters (see example searcher contract)>",
"code": "0x...", // (optional), code for the search contract, otherwise taken from the bot contract address on-chain. Useful if the searcher does not want to reveal search strategy bytecode on-chain
}
],
// remaining eth_sendBundle fields
blockNumber, // (string, optional) hex encoded block number for which this bundle is valid on. If nil or 0, blockNumber will default to the current block
minTimestamp, // (integer, optional) minimum timestamp for which this bundle is valid, in seconds since the unix epoch
maxTimestamp, // (integer, optional) maximum timestamp for which this bundle is valid, in seconds since the unix epoch
revertingTxHashes, // (array[string], optional) list of tx hashes that are allowed to revert or be discarded
replacementUuid, // (string, optional) UUID v4 that can be used to replace or cancel this bundle
refundPercent, // (integer, optional) percentage (from 0 to 100) of the 'refundIndex' transaction ETH rewards that should be refunded back to the 'refundRecipient'
refundRecipient, // (address, optional) address that will receive the ETH refund. Default is sender of the last transaction in the bundle
refundIndex, // (integer, optional) index of the transaction of which the ETH reward should be refunded. Default is last transaction in the bundle
}
]
}
Example Searcher Contract
The off-chain simulated transaction with input data from the API should return some bytes. The first 4 bytes will be used as the function selector for the on-chain transaction and the remaining bytes will be passed as input to this selected function. If the off-chain simulated transaction returns empty data, the bundle will be discarded with no associated cost. This on-chain transaction will be signed by a whitelisted and verifiable Merkle Off-Chain Bundle Signer. It is recommended to add a safeguard in your contract to require the sender to be from this signer address.
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.12 <0.9.0;
contract SearcherContract {
function search(_data bytes) public pure returns (bytes memory) {
// off-chain compute here
// return call data that calls settle() with arguments 1 and 0x0
return abi.encode(this.settle.selector, uint256(1), address(0));
}
function settle(uint256 amountIn, address pool) public returns (uint256) {
require(msg.sender == "<merkle off-chain bundle signer>");
// settlement logic here
uint256 fees = 0; // must pay for on-chain and off-chain gas, remaining is used for priority ordering
block.coinbase.transfer(fees);
return 0;
}
}
Another interesting feature that off-chain bundles allows is spoofing the bot contract with the off-chain execution engine. Searchers can include an optional string encoded bytes of the code they want to call directly in the rpc request since off-chain transactions are simply spoofed simulations. The output of this code still can sellect a function of an on-chain contract to settle a searcher's strategy. This allows searchers to only have to deploy the critical code on-chain lowering the cost of deployment. Since most of the protected trade logic is in the off-chain component, sending the searching component of the contract as code adds a privacy shield from other searchers reverse engineering your MEV strategy. In this example contract, the call to search can be passed in as code data instead of being included in the deployed SearcherContract.
Fees
The cost of an off-chain bundle is derived from the base fee paid to execute the on-chain transaction plus the gas used for the off-chain transaction at a largely subsidize fee rate. The exact calculation of this fee is still TBD. Note that there are no priority fees with off-chain bundles. All fees must be made through a coinbase transfer in the on-chain transaction covering these two costs. All remaining value will be used for priority ordering in the block.
Blind Arbitrage Example
Lets take an example of a blind arbitrage strategy on MEV Share. Lets say there is a new MEV Share transaction that is swapping PEPE/WETH with unknown touched pools, swap amount, and direction. A blind argbitrage strategy would need to check the pool state of multiple PEPE/WETH dex pools across dexes, calculate the optimal swap route through these pools, and then call the two or more swap transactions to execute the arbitrage opportunity. Due to the hidden information of the transaction, all of this computation needs to occur on-chain during bundle execution. With off-chain bundles, the dex pool state reads and optimal route logic can be placed in the search() function of the contract which will execute off-chain at low gas fees and simply return minimal data such as an array of target pools and swap amounts in the order of the swap route. The settle() function can then simply iterate through this array and call the swaps with a final check for profit at the end. While the settlement actions such as swapping must exist on-chain, all other computation can be moved off-chain drastically lowering the cost of the bundle.
Achievements
- Allows a net reduction in MEV gas footprint on Ethereum by optimizing all non-critical computation off-chain. In effect blocks produced under this paradigm will cleanup as much computation associated with MEV as possible and open up blockspace for more transactions.
- Improves innovation and access to arbitrary computation without the consequence of high gas cost.
- Reduces the competitive barrier for new searchers to compete in gas optimized execution.
Risks
Due to the dependency of the builderās simulation as inputs to searchersā MEV bots, there is some level of trust that the builder will act in good faith when executing the on-chain contract call. Merkle promises to uphold this trust by acting in good faith and our builderās actions can be easily verified. Theyāre also safeguards that searchers can implement in their contracts to reduce the risk of loss.
Future
We believe strongly in the benefits of MEV footprint minimization for both searchers and all other participants in the ecosystem. While we initially are building this feature out for searchers, we also look towards potential use cases of this feature for dapp developers and power users such as MEV mitigation, expensive compute optimization, etc!
If this feature sounds exciting or if you have any thought and/or concerns that you would like to discuss together, please come talk to us on discord! We would love to hear back from the community and improve upon our initial ideas here!