.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/economics/fees/plot_01_eip1559_base_fee.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_economics_fees_plot_01_eip1559_base_fee.py: EIP-1559: a base fee, burned (2021), and Roughgarden's analysis (2020) ====================================================================== Until August 2021, Ethereum sold block space as Bitcoin still does: a *first-price auction* in which each user names a fee and pays it if included. No bid is obviously right, so users overpay or wait, and the price swings with every burst of demand. EIP-1559 sets a protocol price per unit of gas, the *base fee*, adjusted after every block toward a target of half the block's capacity, .. math:: b_{t+1} = b_t \left(1 + \frac{1}{8}\,\frac{g_t - g^*}{g^*}\right), which every included transaction pays and which is *burned*; users add a small tip for the producer. Roughgarden showed that outside sudden rises in demand, offering the base fee plus a tip is optimal, that a myopic producer has no reason to deviate, and that off-chain deals between users and producers cannot beat the protocol, because the base fee goes to nobody. The simulation sends the same demand, with a surge in the middle, through both mechanisms over a mempool whose users give up after 20 blocks. .. GENERATED FROM PYTHON SOURCE LINES 28-35 .. code-block:: Python import statistics import matplotlib.pyplot as plt import blockchainkit as bk from blockchainkit.economics.visualizers import plot_fee_market .. GENERATED FROM PYTHON SOURCE LINES 36-38 One demand surge, two mechanisms -------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 38-51 .. code-block:: Python TARGET = 20 * 21_000 # Twenty transfers. arrivals = [20] * 40 + [45] * 40 + [20] * 40 eip1559 = bk.economics.simulate_fee_market(arrivals, gas_target=TARGET, seed=7) auction = bk.economics.simulate_fee_market( arrivals, mechanism="first-price", gas_target=TARGET, seed=7 ) fig, (top, bottom) = plt.subplots(2, 1, figsize=(9, 7), sharex=True) plot_fee_market(eip1559, gas_target=TARGET, ax=top) plot_fee_market(auction, gas_target=TARGET, ax=bottom) fig.tight_layout() .. image-sg:: /api/gallery/economics/fees/images/sphx_glr_plot_01_eip1559_base_fee_001.png :alt: eip1559: block fullness and price, first-price: block fullness and price :srcset: /api/gallery/economics/fees/images/sphx_glr_plot_01_eip1559_base_fee_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 52-54 The base fee finds the price at which demand meets the target ------------------------------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 54-67 .. code-block:: Python before, during = eip1559.base_fees[39], eip1559.base_fees[79] print(f"base fee before the surge {before}, at its end {during}") assert during > 1.5 * before settled = statistics.mean(eip1559.gas_used[60:80]) / TARGET print(f"gas used during the surge, once the fee has adjusted: {settled:.2f} x target") assert 0.8 < settled < 1.2 assert max(eip1559.gas_used) <= 2 * TARGET burned, tips = sum(eip1559.burned), sum(eip1559.producer_revenue) print(f"burned {burned:,}, paid to producers {tips:,}") assert burned > 10 * tips # The producer gains almost nothing from what users pay. .. rst-class:: sphx-glr-script-out .. code-block:: none base fee before the surge 80, at its end 308 gas used during the surge, once the fee has adjusted: 1.07 x target burned 9,220,176,000, paid to producers 100,128,000 .. GENERATED FROM PYTHON SOURCE LINES 68-73 Prices that are easier to predict --------------------------------- Block to block, the base fee moves by at most 12.5%; the first-price auction's clearing price jumps with the bids that happen to arrive. .. GENERATED FROM PYTHON SOURCE LINES 73-89 .. code-block:: Python def jumps(prices): return [abs(b - a) / a for a, b in zip(prices, prices[1:], strict=False) if a] paid = [fee + 2 for fee in eip1559.base_fees] print( f"largest jump: EIP-1559 {max(jumps(paid)):.1%}, " f"first-price {max(jumps(auction.mean_price)):.1%}" ) assert max(jumps(eip1559.base_fees)) <= 0.125 assert max(jumps(auction.mean_price)) > max(jumps(paid)) plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none largest jump: EIP-1559 12.1%, first-price 62.5% .. GENERATED FROM PYTHON SOURCE LINES 90-97 Exercise -------- A producer considers filling its block with its own transactions to push the base fee up for the next producers. What does it pay for that, and who receives it? Use ``next_base_fee`` to compute how many full blocks it takes to double the base fee. A worked solution is in :doc:`/exercises/economics`. .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.153 seconds) .. _sphx_glr_download_api_gallery_economics_fees_plot_01_eip1559_base_fee.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/economics/fees/plot_01_eip1559_base_fee.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_01_eip1559_base_fee.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_01_eip1559_base_fee.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_01_eip1559_base_fee.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_