# MEV Blocker Fee: Rules and Fee Management Smart Contract :::success Update as of 2024-04-15 the canonical version of the MEV Blcoker rules to rely upon, are available [here](https://docs.cow.fi/mevblocker/builders/rules) ::: [TOC] ## Introduction MEV Blocker was created to allow anyone to safely use Ethereum, guaranteeing fast inclusion time, protection from attacks, and rebates whenever there are profitable backrunning opportunities. Achieving these ambitious objectives requires a source of revenue to support the technical development of the product and to drive continuous growth in users' adoption. Furthermore, MEV Blocker wants to be an open, shared infrastructure. As part of this effort, it is important to have clear and transparent rules determining which builders can receive its flow. The purpose of this document is to spell out the rules that builders should follow. One of these rules is that builders should pay a fee. This document also explains the new fee mechanism and its rationale. ## Rules The basic technical requirement to start receiving flow is to build at least 1% of the blocks each week of the previous month. We reserve the right to disconnect a builder who drops significantly below the 1% threshold while connected to MEV blocker. Also, the fee will always be calculated as if the builder won at least 1% of blocks (see the discussion about the fee adjustment below). Connected builders who support refund bundles and replacementUuid(or uuid) for updatable bundles receive MEV Blocker transactions and bundles immediately. These builders *should maximize the refunds received by MEV blocker's users*. In particular, they should, for each transaction, always include the highest-paying bundles plus other bundles that do not fail (in the combination that maximizes the refund). If they comply with this rule, they can perform additional blind, end-of-block backrunning. Connected builders who do not support refund bundles will receive transactions with a delay. The purpose is to give time for searchers connected to MEV Blocker to create bundles. These builders *cannot perform any backrunning (internal, blind, whatever).* Independent of their support for bundles, all builders connected to MEV Blocker are expected to: - Refrain from unethical activities that may hurt MEV Blocker users. This includes (but is not limited to): no frontrunning, no sandwiching, no state or transaction sharing/leaking in any form. - Provide good service. This includes (but is not limited to) the timely inclusion of a transaction (or a bundle) if its effective gas price is larger than the lowest-paying transaction included in the block, with the exception of unavoidable technical limitations (i.e., latency) and legal requirements (i.e., OFAC). - Do not take actions having the sole purpose of gaming the rules or avoiding paying the fee. This includes (but is not limited to) creating a separate identity (a "shadow builder") that only receives MEV blocker flow. - Deposit 10 ETH to a dedicated [smart contract](##MEV-Blocker-Fee-Management-Smart-Contract), administered by MEV blocker implementing partners. These funds will be used to cover late fees and penalties. They will be returned to builders who decide to disconnect from MEV blocker and are in good standing. We reserve the right to disconnect builders suspected of violating these rules. If wrongdoing was established, we reserve the right to charge the violating builder any damage caused and require a re-subscription fee of 2 ETH. For example, suppose a builder included only one bundle while it was possible to include two bundles for the same transaction, hence failing to maximize the refund. Such a builder may be asked to pay as damage the reward from the missing bundle (plus the reconnection fee). Finally, in the future, we may ask connected builders to submit their blocks to Agnostic relay (not exclusively and only blocks containing MEV blocker transactions). This would allow us to create meaningful alerts and metrics by checking, for the same slot, how different builders include the same MEV blocker's transactions/bundles. Also, in a future version of the fee mechanism, we may use data from Agnostic relay to calculate the fee (see below). However, for the moment, these tests and alerts are not in place, and hence, submitting to Agnostic relay is not a requirement. ## The Fee All builders connected to MEV Blocker will pay a per-block-won fee recomputed every period (for example, every month). In practice, at the beginning of period $t$ a builder decides whether to receive flow from MEV blocker. If it decides to do so, for every block won during period $t$ it will pay a per-block fee calculated as a percentage of the the average per-block-won value of exclusive MEV Blocker transactions during the previous period. Mathematically, the per-block fee for period t is a percentage of $$ M_{t-1} = {A_{t-1}-B_{t-1} \over C_{t-1}} $$ Where $A_{t-1}$ = Total MEV Blocker transaction value during period $t-1$, excluding rebates. $B_{t-1}$ = Total value of MEV blocker transactions also in the mempool during period $t-1$. $C_{t-1}$ = Number of blocks mined by builders receiving MEV blocker transactions during period $t-1$. Initially, the fee will be 20% of the above value, and the length of the period will be one month, but these variables may be adjusted later. This [dune query ](https://dune.com/queries/3560043/5990842)calculates the fee for the past 12 months (note that the query is preliminary and may be updated). The per-block won fee for March would have been 0.00048 ETH, and that for April (according to March data so far) will be 0.00059 ETH. Builders who wish to connect or disconnect should announce their intention at least 24 hours before the beginning of the new period (i.e., 24 hours before the fee update). Note that, despite the fact that the fee is per block, it will not be paid with each block: we will keep track of it off-chain and settle it weekly. Hence, the settlement period for the payment (one week) differs from the frequency at which the per-block won fee is computed (one month). Builders are expected to settle their payment within 24 hours from the beginning of the new settlement period using the dedicated [smart contract](##MEV-Blocker-Fee-Management-Smart-Contract). We'll compute the value of the per-block won fee using publicly available data, in a format that is easy to verify (for example, as a Dune query). The process for [posting](####2.-Billing-and-Subscription-Fees) this value onchian, as well as posting builder's dues and payment is documented below in the [smart contract section](##MEV-Blocker-Fee-Management-Smart-Contract). Finally, for builders who won fewer than 1% of blocks during a given week, the fee will be adjusted so that these builders pay as if they won exactly 1% of blocks during the week. In practice, at the end of each week, these builders pay: $$ 1\% (total\ blocks\ mined\ during\ the\ previous\ week) * 20\% M_{t-1} $$ The rationale for this adjustment is that connecting a builder to MEV blocker poses a risk because of the potential leaking of transactions to the public mempool, which should be evaluated against the benefit of faster inclusion of MEV blocker transactions. We believe the risk outweighs the benefit for builders who win less than 1% of blocks. Although we do not want to penalize builders who may temporarily fall below this threshold too harshly, we also want to discourage builders that pose risk to MEV Blocker service, from connecting in the first place. ## Discussion ### Why this fee mechanism? An intuitive notion of fairness dictates that each builder should pay for the value of MEV Blocker transactions it uses. At the same time, an important objective of the mechanism is to be as non-distortionary as possible: it should not affect the decision to include or not include a transaction by a builder. A fee constructed simply as a fraction of the tip of each MEV Blocker transaction risks creating distortion. Furthermore, on the implementation side, it would require a new API. The proposed solution instead does not require any new API and is unlikely to create distortions. It is also built to be correct *on average*: if builders do not disconnect and win more or less the same fraction of blocks between periods, they end up paying with a month delay the average value of MEV transactions they received during the previous week. It is also important to stress that this is the first iteration of the fee mechanism. For example, in the future, we may compute the fee as a fraction of the MEV Blocker tx value included by non-winning builders for the same slot. Intuitively, that would be a proxy for the value from MEV Blocker available to the winning builder, independent of this builder's decision to include this or that transaction. This mechanism cannot be implemented now because Agnostic relay does not store any data regarding blocks built by non-winning builders, but this could change later. ### Who pays the fee? To understand who pays the fee incidence, we need to consider two cases. If a single builder receives MEV Blocker flow, then introducing the fee is at the expense of this builder's profits: if this builder wins, it wins less (by an amount equal to the fee) and is less likely to win because it will bid lower. If, for simplicity, we ignore this second effect, on average, the builder pays 20% of the value of MEV transactions as a fee while keeping the remaining 80% as profits. At the other extreme, suppose that all builders are connected to MEV Blocker, and hence, after the fee is introduced, they all have to pay it. Now, for all builders, winning a block is less valuable by an amount equal to the fee. For the moment, let's think of the auction as a second-price auction: the winning builder is the one who bids the highest but only pays the second-highest bid. One of the most famous results in auction theory is that, in a second-price auction, bidders should bid their true valuation, which for each builder is the value of its block minus MEV blocker fee. This implies that the winning bidder earns the value of its block minus MEV blocker fee, and pays in the auction the second-highest bid, which is the second most valuable block minus MEV blocker fee. Hence, the winning builder earns less but pays less, and its profit margin remains the same. In equilibrium, the only impact of MEV blocker's fee is that all bids are lower, and hence, payments to validators are lower. In equilibrium, the fee is paid indirectly by the validator. Note that the auction is not exactly a second-price auction. It starts as an ascending English auction, where bidders gradually increase their bids. Due to latency, the final part is similar to a first-price sealed bid auction. Despite these complexities, the auction's dynamics are similar to a second-price auction because each builder aims to outbid the second-highest bid by a small margin. Also, since the value a builder gets from creating a block doesn't depend on other builders' blocks (i.e., the auction is in private values), the revenue equivalence theorem says that all auction formats yield the same expected payoff to its participants. Hence, even if the auction is not in second price, we can analyze its equilibrium as if it were in second price. To summarize, we hope that builders will stay connected to MEV Blocker and that the fee will reduce the payments to validators (i.e., MEV). At the same time, we expect the mechanism to be overall beneficial to builders, including in the case where only one or a few builders connect (and end up paying the fee out of their profits). ### Possible Challenges The main possible challenge (and where the above reasoning would fail) is when builders have blocks of very low value, so imposing a fee turns the value of winning negative. In such cases, builders connected to MEV blocker may not bid. As a consequence, either a non-connected builder wins the block, or a validator creates a vanilla block, or the block is empty. To check whether this possibility is empirically relevant, we calculated what the fee would have been and checked how many times the block won by a builder had a lower value than the fee (see [this Dune query](https://dune.com/queries/3565473)). We found 18 such cases in 2024 so far. For context, there were more than 630.000 blocks mined so far in 2024. A final possible challenge is that the mechanism is designed to be "correct" on average, in the sense that, on average, a builder who does not disconnect pays with one period delay 20% of the value of MEV blocker transactions it received. However, averages may be misleading, especially for small builders. Therefore, for each connected builder, we will keep track of the value of MEV blocker transactions received during a month and the total fee paid to MEV blocker in the subsequent month. If we find cases in which the fee paid exceeds the value received, we will consider adjustments to the fee mechanism (for example, instead of charging 20%, charging 15% or 10%). ## MEV Blocker Fee Management Smart Contract :::success The contract's [github repo](https://github.com/cowprotocol/mev-blocker-till/), and [mainnet deployment address](https://etherscan.io/address/0x08cd77feb3fb28cc1606a91e0ea2f5e3eaba1a9a#code) are available as of April 5th. ::: The MEV Blocker Fee Management Smart Contract provides a framework for managing financial interactions between builders and the MEV Blocker service. This documentation guides builders through the process of engaging with MEV Blocker, from making initial deposits to managing subscription fees, and eventually withdrawing their deposits if they choose to disconnect. ### Contract Overview The smart contract is designed to handle: - **Deposits** (bonds) from builders wishing to receive transaction order flow from MEV Blocker. - **Weekly billing** of subscription fees. - **Advertising** the price of the subscription. - **Payment** of dues by builders. - **Withdrawal** of deposits by builders who wish to disconnect. ### Key Functionalities #### 1. Joining MEV Blocker Builders interested in joining must call the `join` function with a deposit of 10 ETH (or the specified initial bond amount). This deposit acts as a bond to cover potential late fees and penalties. **Function to Use:** ```solidity function join() payable external ``` #### 2. Billing and Subscription Fees MEV Blocker will use the `bill` function on a weekly basis to update the bills of subscribed builders for the previous period and update the subscription fee for the next period. The new price will be applied as of the next block. The current price can be queried at any time. **Functions for MEV Blocker Admins:** ```solidity function bill(address[] calldata ids, uint256[] calldata due, uint256 newPrice) external onlyBiller ``` Builders are responsible for monitoring their dues and ensuring timely payment through the `pay` function. Bills remaining unpaid for >24h will result in the corresponding builder being disconnected. **Function for Builders:** ```solidity function pay(address id) payable external ``` #### 3. Managing Dues and Withdrawals Builders wishing to disconnect from MEV Blocker must first signal their intention by calling the `nope` function. After a waiting period of 7 days, they may withdraw their bond by invoking the `exit` function, provided all dues have been settled. **Functions for Exiting:** ```solidity function nope() external function exit() external ``` #### 4. Handling Forced Payments and Penalties The contract owner has the authority to withdraw from bonds or impose fines on builders for violations of the rules set forth by MEV Blocker. The `fine` function includes a `to` address which facilitates direct reimbursement to affected parties. **Functions for Contract Owner:** ```solidity function draft(address id, uint256 amt) external onlyOwner function fine(address id, uint256 amt, address to) external onlyOwner ``` ### Usage Guide for Builders 1. **Making the Initial Deposit:** - To participate, send a transaction with 10 ETH to the `join` function of the contract. 2. **Monitoring Subscription Fees:** - Keep an eye on the advertised subscription fee and ensure sufficient funds are available to cover weekly dues. 3. **Paying Dues:** - Use the `pay` function to settle your weekly dues. Ensure the correct amount is sent to avoid any disruptions in service. 4. **Withdrawing Deposits:** - If you decide to disconnect, call `nope` to signal your intention. After 7 days, you can withdraw your deposit through the `exit` function, assuming all dues are cleared. This documentation is intended to facilitate a smooth and informed engagement with the MEV Blocker service by builders. For further assistance or inquiries, builders are encouraged to contact the MEV Blocker team. ### Contract Code The contract code is provided below and is also available in the following [GitHub repo]() (link to be updated). The contract is scheduled to be reviewed by Friday, April 5th, and could undergo some changes following the review. The contract is expected to be deployed to the Ethereum mainnet by Monday, April 8th. The contract will be verified, and the contract address will be added to this document. ```solidity // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.6; contract MevBlockerFeeTill { // --- key invariant --- // this.balance == earned + sum(bonds) // --- events --- event LogNote( bytes4 indexed sig, bytes32 indexed arg1, bytes32 indexed arg2 ) anonymous; modifier note { _; assembly { // log an 'anonymous' event with no data and three indexed topics: // the selector and the first two args log3(0, 0, shl(224, shr(224, calldataload(0))), // msg.sig calldataload(4), // arg1 calldataload(36) // arg2 ) } } // --- auth --- address payable public owner; mapping (address => bool) public billers; modifier onlyOwner { require(msg.sender == owner, "not owner"); _; } modifier onlyBiller { require(billers[msg.sender] == true, "not biller"); _; } constructor(address _owner) { owner = payable(_owner); } function pass(address whom) external note onlyOwner { owner = payable(whom); } function rely(address whom) external note onlyOwner { billers[whom] = true; } function deny(address whom) external note onlyOwner { billers[whom] = false; } // --- bonding --- uint256 public wait = 7 days; mapping (address => uint256) public bonds; mapping (address => uint256) public noped; function join() payable external note { bonds[msg.sender] += msg.value; noped[msg.sender] = 0; } // --- billing --- event PriceUpdate(uint256 newPrice); mapping (address => uint256) public dues; uint256 public price; uint256 public earned; function bill(address[] calldata ids, uint256[] calldata due, uint256 newPrice) external onlyBiller { for (uint256 i = 0; i < ids.length; i++) { dues[ids[i]] += due[i]; } price = newPrice; emit PriceUpdate(newPrice); } function unbill(address[] calldata ids, uint256[] calldata undue) external onlyOwner { for (uint256 i = 0; i < ids.length; i++) { dues[ids[i]] -= undue[i]; } } function pay(address id) payable external note { dues[id] -= msg.value; earned += msg.value; } // --- forced payments --- function draft(address id, uint256 amt) external onlyOwner note { bonds[id] -= amt; dues[id] -= amt; earned += amt; } function fine(address id, uint256 amt, address to) external onlyOwner note { bonds[id] -= amt; payable(to).transfer(amt); } // --- withdrawing --- function nope() external note { noped[msg.sender] = block.timestamp; } function exit() external note { require(noped[msg.sender] != 0, "didn't nope"); require(block.timestamp > noped[msg.sender] + wait, "too early"); require(dues[msg.sender] == 0, "didn't pay"); uint256 bond = bonds[msg.sender]; bonds[msg.sender] = 0; payable(msg.sender).transfer(bond); } function reap() external note onlyOwner { uint256 amt = earned; earned = 0; payable(msg.sender).transfer(amt); } } ```