# Dubious Math Around Builder Reveal Timing Games ## The Problem at Hand An under-researched topic has emerged in the discussion of [EIP-7732](https://eips.ethereum.org/EIPS/eip-7732) around builders playing reveal timing games to exercise an option. Here's an example to illustrate the basic idea: Suppose at time $t=0$ three things happen: 1. The builder places a trade to **sell** $Q$ ETH on a DEX at price $P_0$ at the top of their block. 2. The builder's block is chosen by the proposer. 3. The builder places a trade to **buy** $Q$ ETH on a CEX at a price $P < P_0$ to pocket the arbitrage. Suppose the total MEV (in ETH) in the block is $M$ and the builder had to pay some fraction $x M$ of it to the proposer in order for their block to be selected. Now suppose at time $t = Δt$ later two things happen: 1. The ETH/USD price on the CEX moves to $P^{*} > P_0$. 2. The builder has not yet revealed the final blob to this block, and there is still time to reveal In this scenario, the builder now has a choice. If they reveal, their profit from the block will be: $$ P_{\text{reveal}} = M - x M $$ But on the other hand, they could choose not to reveal that final blob. And if they don't release that blob, they will have cancelled their initial trade to sell $Q$ ETH at price $P_0$. If they went that route, they could choose to instead sell the $Q$ ETH they bought on the CEX at $t=0$ at this new higher price of $P^{*}$. Note that in doing this, they would still have to pay the proposer their promised bid value $M x$. In this scenario, the builder's profit becomes: $$ P_{\text{withhold}} = Q (P^{*} - P_0) - xM $$ Thus, a purely profit-maximizing builder may choose not to reveal when: $$ P_\text{withhold} > P_\text{reveal} \Longleftrightarrow Q(P^{*} - P_0) > M $$ Rearranging gives the *price-jump threshold*: $$ \frac{P^{*}}{P_0} > 1 + \frac{M}{Q} $$ This expression was derived assuming the builder sold on chain, but the symmetric argument can be used for the builder placing a buy on chain instead. Needless to say, this is an issue. We don't want builders creating chain instability by refusing to reveal. ## Can we Quantify the Likelihood of this? Maybe. I'm about to do some math for which I am entirely unqualified for. Buckle up. This scenario is essentially a one-sided, early-exercisable barrier option with path-dependence: * Path-dependent: the builder watches the market over the interval $0 \dots \Delta t$ * Direction-sensitive: the builder only exercises the option (by not revealing) if the price moves in the profitable direction (up, if they placed a DEX sell) * Early exercisable: they can act (by placing a CEX trade) at any time during the window, not just at the end * Single-barrier knock-in option: once price hits the threshold, they act If we treat the *log-price* $\,\ln S_t\,$ as a **drift-free Geometric Brownian Motion (GBM)** with volatility $\sigma$, we can ask a classic barrier-option question: > **What is the probability that this GBM touches or exceeds a fixed barrier before a deadline $\tau$?** For an **up-barrier** the answer has an exact closed form involving the complementary error function $\operatorname{erfc}$. Let $$ b = \ln\!\Bigl(\tfrac{P^{*}}{P_0}\Bigr) \;=\; \ln\!\bigl(1 + \tfrac{M}{Q}\bigr) $$ be the *log-distance* from the current price $P_0$ to the profit-making threshold $P^{*}$. Then the probability that the price crosses that barrier **at least once** in the time interval $\tau$ is $$ \Pr\!\bigl[\text{hit in } \tau\bigr] \;=\; \operatorname{erfc}\!\Bigl( \frac{b}{\sigma\,\sqrt{2\,\tau}} \Bigr). $$ --- ### Why these three inputs drive the odds * **Smaller $M/Q$** → lower barrier $b$ → larger hit probability. *One would expect, in practice, that $M$ would rise with $Q$, so very small $M/Q$ pairs should be rare. It would be interested to try and quantify this with on-chain data.* * **Higher volatility $\sigma$** spreads GBM paths faster → higher chance of a hit. * **Longer window $\tau$** obviously gives the price more time to reach the barrier. > If any one of those three moves the opposite way (e.g.\ realised 1-month ETH/USD volatility is only $\sigma \approx 0.60$ annualised), the term inside $\operatorname{erfc}(\cdot)$ grows and the hit probability shrinks exponentially. We can write a script to plot this probability. We just need sensible values for $M$, $Q$, $\sigma$, and $\tau$. Based on the latest proposal for [dual deadline PTC](https://notes.ethereum.org/@anderselowsson/Dual-deadlinePTCvote), the maximum `τ` is about 8.5 seconds. If we want $M$ to be small, we might choose $M = 0.02\text{ ETH}$ to give it a fairly high chance. We could maximize volatility by setting $\sigma=1.0$ . Now the biggest unknown is $Q$. We don't really move the needle until $Q=15 \text{ ETH}$ with a 1% probabilty at 8.5 seconds: ![](https://notes.ethereum.org/_uploads/SyTZgPlUlg.png) I really have no idea how likely it would be for a builder to place a $15 \text{ ETH}$ trade to make only a $0.02 \text{ ETH}$ profit from arbitrage. Things get worse at $Q=50 \; \text{ETH}$ with the same profit of $M = 0.02 \text{ ETH}$: ![](https://notes.ethereum.org/_uploads/HJROxvx8xg.png) You can play with these parameters yourself: ```python #!/usr/bin/env python3 import numpy as np, matplotlib.pyplot as plt from scipy.special import erfc # ------- ETH-denominated inputs ------------------------------------ M_tot_eth = 0.02 # total MEV per block, in ETH Q_eth = 50 # ETH size of the on-chain arbitrage leg sigma = 1.00 # annualised vol (100 %/yr) for ETH/USDC price # ------------------------------------------------------------------- delta = M_tot_eth / Q_eth # fractional move needed barrier = 1 + delta # P*/P0 b = np.log(barrier) # log-barrier for GBM seconds = np.linspace(0.05, 12.0, 400) # reveal window (s) tau = seconds / (365*24*60*60) # in years hit_prob = erfc( b / (sigma * np.sqrt(2*tau)) ) plt.figure(figsize=(7,4)) plt.plot(seconds, hit_prob) plt.xlabel("Reveal window τ (seconds)") plt.ylabel("Pr[ price ever ≥ barrier ]") plt.title(f"Trade size = {Q_eth} ETH | Required move = {delta*100:.2f}% | σ={sigma:.0%}/yr") plt.ylim(0,1); plt.grid(alpha=.4,ls="--"); plt.tight_layout(); plt.show() ```