Published on

Off-Chain Bundles

Authors
Monetize your wallet transactions today.
šŸ‘‹ Welcome to our Engineering blog. merkle specializes in MEV protection and monetization on Ethereum. We guarantee minimum $0.10 per transaction. Ideal for Wallets and RPC Providers looking to protect their customers against Sandwiches while generating revenue.

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!

RETH RPC
The first RPC service powered by RETH, 20ms faster on average and 10x cheaper.
Sign up
Transaction Stream
Stream all Ethereum, Polygon and BSC transactions to your application in real-time. Faster than any transaction stream on the market. Built with RETH.
Sign up
Simulation API
Simulate bundles of up to 10 transactions on Ethereum, Polygon and BSC for $0.2 / 1,000,000,000 of gas.
Sign up