-
Notifications
You must be signed in to change notification settings - Fork 25
/
eip1559.html
20088 lines (19490 loc) · 582 KB
/
eip1559.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html>
<head><meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>EIP 1559: A transaction fee market proposal</title>
<meta property="og:title" content="EIP 1559: A transaction fee market proposal" />
<meta property="og:url" content="https://ethereum.github.io/abm1559/notebooks/eip1559.html" />
<meta property="og:image" content="https://ethereum.github.io/rig/static/rig.png" />
<meta property="og:description" content="Introduction to EIP 1559 dynamics" />
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="EIP 1559: A transaction fee market proposal">
<meta name="twitter:description" content="Introduction to EIP 1559 dynamics">
<meta name="twitter:image" content="https://ethereum.github.io/rig/static/rig.png">
<script src="https://cdn.jsdelivr.net/npm/underscore@1.13.1/underscore-umd-min.js" type="text/javascript"></script>
<script src="https://ethereum.github.io/rig/static/react.development.js"></script>
<script src="https://ethereum.github.io/rig/static/react-dom.development.js"></script>
<script src="https://ethereum.github.io/rig/static/component-library.js"></script>
<script src="https://ethereum.github.io/rig/static/header.js"></script>
<script src="https://ethereum.github.io/rig/static/footer.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
<style type="text/css">
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: var(--jp-cell-editor-active-background) }
.highlight { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }
.highlight .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */
.highlight .err { color: var(--jp-mirror-editor-error-color) } /* Error */
.highlight .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */
.highlight .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */
.highlight .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */
.highlight .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */
.highlight .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */
.highlight .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */
.highlight .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */
.highlight .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */
.highlight .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */
.highlight .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */
.highlight .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */
.highlight .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */
.highlight .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */
.highlight .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */
.highlight .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */
.highlight .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */
.highlight .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */
.highlight .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */
.highlight .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */
.highlight .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */
.highlight .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */
.highlight .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */
.highlight .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */
.highlight .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */
.highlight .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */
.highlight .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */
.highlight .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */
.highlight .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */
.highlight .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */
.highlight .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */
.highlight .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */
</style>
<link rel="stylesheet" type="text/css" href="https://ethereum.github.io/rig/static/jupyter.css"/>
<link rel="stylesheet" type="text/css" href="https://ethereum.github.io/rig/static/theme-light.css"/>
<style type="text/css">
a.anchor-link {
display: none;
}
.highlight {
margin: 0.4em;
}
/* Input area styling */
.jp-InputArea {
overflow: hidden;
}
.jp-InputArea-editor {
overflow: hidden;
}
@media print {
body {
margin: 0;
}
}
</style>
<!-- Load mathjax -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/latest.js?config=TeX-MML-AM_CHTML-full,Safe"> </script>
<!-- MathJax configuration -->
<script type="text/x-mathjax-config">
init_mathjax = function() {
if (window.MathJax) {
// MathJax loaded
MathJax.Hub.Config({
TeX: {
equationNumbers: {
autoNumber: "AMS",
useLabelIds: true
}
},
tex2jax: {
inlineMath: [ ['$','$'], ["\\(","\\)"] ],
displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
processEscapes: true,
processEnvironments: true
},
displayAlign: 'center',
CommonHTML: {
linebreaks: {
automatic: true
}
},
"HTML-CSS": {
linebreaks: {
automatic: true
}
}
});
MathJax.Hub.Queue(["Typeset", MathJax.Hub]);
}
}
init_mathjax();
</script>
<!-- End of mathjax configuration -->
<link rel="stylesheet" type="text/css" href="https://ethereum.github.io/rig/static/index.css"/>
</head>
<body class="jp-Notebook" data-jp-theme-light="true" data-jp-theme-name="JupyterLab Light">
<div id="header"></div>
<script>
ReactDOM.render(
e(Header, null),
document.querySelector("#header")
);
const hamburger = document.querySelector(".hamburger");
const navMenu = document.querySelector(".nav-menu");
function mobileMenu() {
hamburger.classList.toggle("active");
navMenu.classList.toggle("active");
}
function closeMenu() {
hamburger.classList.remove("active");
navMenu.classList.remove("active");
}
hamburger.addEventListener("click", mobileMenu);
const navLink = document.querySelectorAll(".nav-link");
navLink.forEach(n => n.addEventListener("click", closeMenu));
</script>
<div class="article-container">
<div class="document-container">
<div class="title-container">
<div class="title">
EIP 1559: A transaction fee market proposal
</div>
<div class="sub-title">
</div>
</div>
<div id="toc-author-block">
<div id="authors"></div>
<div id="toc"></div>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<h2 id="TL;DR">TL;DR<a class="anchor-link" href="#TL;DR">¶</a></h2><ul>
<li>EIP 1559 is a proposed improvement for the transaction fee market. It sets a variable "base" gasprice to be paid by the user and burned by the protocol, in addition to a "tip" paid by the user to the block producer.</li>
<li>When many transactions compete for limited space, the basefee goes up. When few transactions are included in the block, the basefee goes down.</li>
<li>We simulate simple demand scenarios and progressively iterate, painting a picture of the mechanism's dynamics. We leave analysis of strategic interactions and a more sophisticated demand behaviour for later work.</li>
</ul>
<hr>
<p><a href="https://eips.ethereum.org/EIPS/eip-1559">EIP 1559</a> is perhaps one of the most anticipated upgrades to the economic model of Ethereum. Proposed by Vitalik Buterin in his <a href="https://github.com/ethereum/research/blob/master/papers/pricing/ethpricing.pdf">Blockchain Resource Pricing</a> paper, the mechanism seeks to replace the first-price auction model governing the current fee market for transaction inclusion.</p>
<h2 id="Why-EIP-1559?">Why EIP 1559?<a class="anchor-link" href="#Why-EIP-1559?">¶</a></h2><h3 id="Transactions-101">Transactions 101<a class="anchor-link" href="#Transactions-101">¶</a></h3><p>Users submit <em>transactions</em> to interact with a blockchain. In Ethereum, these transactions can be as simple as sending ether from one account to another, or as complex as making a contract perform something on your behalf (entering a lottery, executing a trade etc). In the latter case, your transaction might trigger other transactions to execute, cascading until no more side-effects take place. It is clear that the simple transfer is much less computation than a complex, multistage transaction, so we measure how much resources each transaction requires by how much <em>gas</em> the transaction (and its potential cascading transactions) needs to execute.</p>
<p>The Ethereum Virtual Machine (EVM), which processes these transactions, has a cost in gas for each elementary operation: adding numbers, storing a value, transfering ether. All transactions are made up of an arbitrary number of these elementary operations (even the really complex ones!) Together, these elementary operations tally up to the gas necessary to process the entire transaction.</p>
<table>
<thead><tr>
<th></th>
<th>Transaction operations</th>
<th>Gas</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Add</td>
<td>20</td>
</tr>
<tr>
<td>2</td>
<td>Transfer</td>
<td>100</td>
</tr>
<tr>
<td></td>
<td><strong>Transaction total</strong></td>
<td>120</td>
</tr>
</tbody>
</table>
<p>But space is scarce, as blocks are produced on a regular interval and offer only a limited amount of available gas. To avoid congestion, transaction senders ("users") price the gas they seek to use, e.g., specifying that they are ready to pay 6 Gwei per unit of gas to have their transaction included.</p>
<table>
<thead><tr>
<th>Transaction gas</th>
<th>Gas price (Gwei)</th>
<th>Total fee (Gwei)</th>
</tr>
</thead>
<tbody>
<tr>
<td>120</td>
<td>6</td>
<td>720</td>
</tr>
</tbody>
</table>
<h3 id="Auctions-as-market-mechanism">Auctions as market mechanism<a class="anchor-link" href="#Auctions-as-market-mechanism">¶</a></h3><p>In the current auction model, block producers typically select a set of the highest paying transactions, making sure that the total gas required by all transactions in the set does not exceed the limit amount of gas offered in a block. Users with selected transactions end up paying the gas price they specified, times the amount of gas their transaction required to be processed. Thus, users "pay what they bid": this is a <em>first-price</em> auction.</p>
<p>In the following table, we assume the block gas limit is 1,000. Though there is a transaction (the last one) paying out 700 Gwei, the block producer cannot include it as it would break the gas limit and thus prefers to include the first, 720 Gwei-valued, transactions. Users pay exactly the fee stated in the column.</p>
<table>
<thead><tr>
<th>Transaction gas</th>
<th>Gas price (Gwei)</th>
<th>Total fee (Gwei)</th>
<th>Included?</th>
<th>Cumulative gas</th>
</tr>
</thead>
<tbody>
<tr>
<td>120</td>
<td>6</td>
<td>720</td>
<td>Yes</td>
<td>120</td>
</tr>
<tr>
<td>200</td>
<td>5</td>
<td>1000</td>
<td>Yes</td>
<td>320</td>
</tr>
<tr>
<td>700</td>
<td>1</td>
<td>700</td>
<td>No</td>
<td>320</td>
</tr>
</tbody>
</table>
<p>The first-price auction has many defects. In its simplest theoretical model, where users bid simultaneously and privately, it is a well-known result that first-price auction are not incentive-compatible, meaning that users do not have the incentive to bid their true value for the transaction being included (you can see why in <a href="https://www.cs.ubc.ca/~cs532l/gt2/slides/11-4.pdf">these slides by Jackson, Leyton-Brown and Shoham, from slide 5 onwards</a>). <em>Second-price</em> auctions are though, when the winner of the auction pays the bid offered by the second-highest bidder.</p>
<p>So second-price auctions were considered as an alternative, but while we could hold Sotheby's accountable for manipulating the result of an auction, we can't quite always do that in the blockchain setting. Since block producers have the final say on who gets included or not, they can "stuff" the blocks with phony transactions from themselves to pump up the "second price", and thus trick the protocol into giving them more than what the market should offer while leaving honest fee-paying transactions by the curb (<a href="https://arxiv.org/abs/1901.06830">this can be somewhat mitigated (Basu et al., 2019)</a> (and <a href="https://web.stanford.edu/~mohamwad/CredibleMechanisms.pdf">there are even results (Akbarpour, Li, 2019)</a> for the case when Sotheby's cannot be held accountable)).</p>
<h3 id="Pricing-congestion-and-EIP-1559">Pricing congestion and EIP 1559<a class="anchor-link" href="#Pricing-congestion-and-EIP-1559">¶</a></h3><p>Enters EIP 1559, written up in an <a href="https://eips.ethereum.org/EIPS/eip-1559">Ethereum improvement protocol (EIP) suggestion by Eric Conner of EthHub fame and Buterin himself</a>. The proposal involves setting a variable <em>basefee</em> to be paid by anyone who wishes to have a transaction included, with the base fee varying according to how empty or how full blocks are. The block limit is set to a fairly high value, while the EIP 1559 mechanism targets a fixed <em>block size</em> (<a href="https://ethgasstation.info/blog/ethereum-block-size/">the amount of gas spent by transactions in the block</a>).</p>
<p>In dire times, when everyone is trying to upgrade their CryptoKitty or frantically closing out their debt positions, block sizes increase as more users are willing to pay the current basefee. In this case, the mechanism increases the basefee to price out users who just don't want it bad enough, returning block sizes to their fixed target. Alternatively, when the chain is an open empty road to nowhere, we would prefer to encourage users to send their transactions in for cheap, so basefee should be much lower.</p>
<p>Under the auction market though, if a lot of people want to transact on the chain at the same time, the threshold bids making it into the blocks should steadily increase (and indeed, have done so in the past). Isn't that the same outcome as EIP 1559? Complicating things, we'll also see in our simulations that users can specify a "tip" paid out to the block producers, in addition to the basefee. A higher tip gets you to the end of the line faster, kind of like the auction mechanism does already. So why do we care about a mechanism seemingly not so different from the auction?</p>
<table>
<thead><tr>
<th>Basefee (burned)</th>
<th>Tip (paid to block producer)</th>
<th>Total fee</th>
</tr>
</thead>
<tbody>
<tr>
<td>4</td>
<td>1</td>
<td>5</td>
</tr>
</tbody>
</table>
<p>One clue is predictability. First-price auctions are notoriously hard to analyse even in the best of cases. It gets worse when bids are open (as they are to anyone who listens to the <em>mempool</em> where user transactions languish before being included) and replaceable (as they are, though not so trivially, with transaction-replacement operations). There is hope that a more "algorithmic" price discovery mechanism will help remove this variability, even when demand fluctuates swiftly (we'll see some of that in the simulations below).</p>
<p>Another clue is analytic simplicity. Pricing things, and especially congestion, in the most parsimonious manner is one object of algorithmic game theory, which is the study of mechanisms from the computational lens. We know from Pigou, Vickrey and a long line of economists that we usually like to <em>internalise externalities</em>, i.e., make people pay for not only what they are doing <em>for</em> themselves, but also what they are doing <em>to</em> others.</p>
<p>When I am on the road in the morning, I impose my presence to everyone else also on the road, and vice-versa. This is why the most fundamental result in this pillar of the discipline states that the correct price to pay for people cramming in some resource is exactly the <em>marginal price</em>: the price of the extra inconvenience for everyone else that your presence imposes. With first-price auctions, it is not clear that we ever get to that price. But a mechanism seeking to achieve some target (e.g., the amount of gas used by a block) and raising/lowering the price (e.g., the basefee) to meet that target gets much closer to this marginal price. And if that is simpler for us to analyse, that also means we get to predict a bit better how the mechanism will behave. Double whammy!</p>
<p>But ok, after this long intro, let's dive into the mechanics of the... ahem... mechanism. We'll first set up a simple <a href="https://github.com/BenSchZA/radCAD">radCAD environment</a> and progressively add on to it to simulate more and more complex phenomena.</p>
<h2 id="The-environment">The environment<a class="anchor-link" href="#The-environment">¶</a></h2><p>First, we define a simple <code>Transaction</code> class, as these are the base element of our simulation. Users produce transactions, which are sent to block producers who must select which of these transactions to include. Under EIP 1559, users specify two things:</p>
<ul>
<li>The <em>gas premium</em>, i.e., the "tip" to the block producers.</li>
<li>The <em>fee cap</em>, i.e., the highest gas price they are willing to pay.</li>
</ul>
<p>As before, users also specify a gas limit for their transaction. If the transaction ends up consuming more gas than the specified gas limit, it is reverted without changes to the chain.</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">secrets</span>
<span class="o">%</span><span class="k">config</span> InlineBackend.figure_format = 'svg'
<span class="k">class</span> <span class="nc">Transaction</span><span class="p">:</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">gas_premium</span><span class="p">,</span> <span class="n">fee_cap</span><span class="p">,</span> <span class="n">gas_used</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">gas_premium</span> <span class="o">=</span> <span class="n">gas_premium</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fee_cap</span> <span class="o">=</span> <span class="n">fee_cap</span>
<span class="bp">self</span><span class="o">.</span><span class="n">gas_used</span> <span class="o">=</span> <span class="n">gas_used</span>
<span class="bp">self</span><span class="o">.</span><span class="n">tx_hash</span> <span class="o">=</span> <span class="n">secrets</span><span class="o">.</span><span class="n">token_bytes</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span>
<span class="k">def</span> <span class="fm">__lt__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">gas_premium</span> <span class="o"><</span> <span class="n">other</span><span class="o">.</span><span class="n">gas_premium</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>Second, we'll grab a few constants from the EIP, possibly looking to change them later on.</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">constants</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"BASEFEE_MAX_CHANGE_DENOMINATOR"</span><span class="p">:</span> <span class="mi">8</span><span class="p">,</span>
<span class="s2">"TARGET_GAS_USED"</span><span class="p">:</span> <span class="mi">12500000</span><span class="p">,</span>
<span class="s2">"MAX_GAS_EIP1559"</span><span class="p">:</span> <span class="mi">25000000</span><span class="p">,</span>
<span class="s2">"INITIAL_BASEFEE"</span><span class="p">:</span> <span class="mi">1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">10</span> <span class="o">**</span> <span class="mi">9</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>Remember that we set up our cadCAD simulations as a repeating pattern of state updates and policies. For this simulation, here is our plan:</p>
<ol>
<li><strong>(State update)</strong> <code>update_demand</code>: Users generate some demand, a list of transactions added to the mempool.</li>
<li><strong>(Policy)</strong> <code>include_all_txs</code>: We have more space to define what our policies are. For now, our block producers will include all transactions in the mempool inside their blocks (we'll make sure that the total amount of gas required won't exceed the gas limit in blocks).</li>
<li><strong>(State update)</strong> <code>update_basefee</code>: Given the included transaction, the protocol checks whether the basefee needs to be updated or not. We'll go deeper into how this update works later on, for now, simply keep in mind that the fee should decrease as our blocks won't be full.</li>
</ol>
<p>We represent the demand as a dictionary with keys given by the transaction hashes. This allows for efficient removal of already-included transactions from the demand pool, which we'll do in a later section.</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
<span class="kn">from</span> <span class="nn">radcad</span> <span class="kn">import</span> <span class="n">Model</span><span class="p">,</span> <span class="n">Simulation</span><span class="p">,</span> <span class="n">Experiment</span>
<span class="kn">from</span> <span class="nn">radcad.engine</span> <span class="kn">import</span> <span class="n">Engine</span><span class="p">,</span> <span class="n">Backend</span>
<span class="c1"># step 1</span>
<span class="k">def</span> <span class="nf">update_demand</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">substep</span><span class="p">,</span> <span class="n">state_history</span><span class="p">,</span> <span class="n">previous_state</span><span class="p">,</span> <span class="n">policy_input</span><span class="p">):</span>
<span class="n">demand</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
<span class="n">tx</span> <span class="o">=</span> <span class="n">Transaction</span><span class="p">(</span>
<span class="n">gas_premium</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">*</span> <span class="p">(</span><span class="mi">10</span> <span class="o">**</span> <span class="mi">9</span><span class="p">),</span>
<span class="n">gas_used</span> <span class="o">=</span> <span class="mi">21000</span><span class="p">,</span>
<span class="n">fee_cap</span> <span class="o">=</span> <span class="mi">6</span> <span class="o">*</span> <span class="p">(</span><span class="mi">10</span> <span class="o">**</span> <span class="mi">9</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">demand</span><span class="p">[</span><span class="n">tx</span><span class="o">.</span><span class="n">tx_hash</span><span class="p">]</span> <span class="o">=</span> <span class="n">tx</span>
<span class="k">return</span> <span class="p">(</span><span class="s2">"demand"</span><span class="p">,</span> <span class="n">demand</span><span class="p">)</span>
<span class="c1"># step 2</span>
<span class="k">def</span> <span class="nf">include_all_txs</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">substep</span><span class="p">,</span> <span class="n">state_history</span><span class="p">,</span> <span class="n">previous_state</span><span class="p">):</span>
<span class="n">demand</span> <span class="o">=</span> <span class="n">previous_state</span><span class="p">[</span><span class="s2">"demand"</span><span class="p">]</span>
<span class="n">basefee</span> <span class="o">=</span> <span class="n">previous_state</span><span class="p">[</span><span class="s2">"basefee"</span><span class="p">]</span>
<span class="n">miner_gains</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">total_gas_used</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">tx_hash</span><span class="p">,</span> <span class="n">tx</span> <span class="ow">in</span> <span class="n">demand</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
<span class="n">gas_price</span> <span class="o">=</span> <span class="nb">min</span><span class="p">([</span><span class="n">basefee</span> <span class="o">+</span> <span class="n">tx</span><span class="o">.</span><span class="n">gas_premium</span><span class="p">,</span> <span class="n">tx</span><span class="o">.</span><span class="n">fee_cap</span><span class="p">])</span>
<span class="n">miner_gains</span> <span class="o">+=</span> <span class="p">(</span><span class="n">gas_price</span> <span class="o">-</span> <span class="n">basefee</span><span class="p">)</span> <span class="o">*</span> <span class="n">tx</span><span class="o">.</span><span class="n">gas_used</span>
<span class="n">total_gas_used</span> <span class="o">+=</span> <span class="n">tx</span><span class="o">.</span><span class="n">gas_used</span>
<span class="k">assert</span> <span class="n">miner_gains</span> <span class="o">>=</span> <span class="mi">0</span>
<span class="k">return</span> <span class="p">{</span> <span class="s2">"gas_used"</span><span class="p">:</span> <span class="n">total_gas_used</span> <span class="p">}</span>
<span class="c1"># step 3</span>
<span class="k">def</span> <span class="nf">update_basefee</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">substep</span><span class="p">,</span> <span class="n">state_history</span><span class="p">,</span> <span class="n">previous_state</span><span class="p">,</span> <span class="n">policy_input</span><span class="p">):</span>
<span class="n">gas_used</span> <span class="o">=</span> <span class="n">policy_input</span><span class="p">[</span><span class="s2">"gas_used"</span><span class="p">]</span>
<span class="n">basefee</span> <span class="o">=</span> <span class="n">previous_state</span><span class="p">[</span><span class="s2">"basefee"</span><span class="p">]</span>
<span class="n">delta</span> <span class="o">=</span> <span class="n">gas_used</span> <span class="o">-</span> <span class="n">constants</span><span class="p">[</span><span class="s2">"TARGET_GAS_USED"</span><span class="p">]</span>
<span class="n">new_basefee</span> <span class="o">=</span> <span class="n">basefee</span> <span class="o">+</span> <span class="n">basefee</span> <span class="o">*</span> <span class="n">delta</span> <span class="o">//</span> <span class="n">constants</span><span class="p">[</span><span class="s2">"TARGET_GAS_USED"</span><span class="p">]</span> <span class="o">//</span> <span class="n">constants</span><span class="p">[</span><span class="s2">"BASEFEE_MAX_CHANGE_DENOMINATOR"</span><span class="p">]</span>
<span class="k">return</span> <span class="p">(</span><span class="s2">"basefee"</span><span class="p">,</span> <span class="n">new_basefee</span><span class="p">)</span>
<span class="n">psub</span> <span class="o">=</span> <span class="p">[{</span>
<span class="s2">"policies"</span><span class="p">:</span> <span class="p">{},</span>
<span class="s2">"variables"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"demand"</span><span class="p">:</span> <span class="n">update_demand</span> <span class="c1"># step 1</span>
<span class="p">}</span>
<span class="p">},</span> <span class="p">{</span>
<span class="s2">"policies"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"gas_used"</span><span class="p">:</span> <span class="n">include_all_txs</span> <span class="c1"># step 2</span>
<span class="p">},</span>
<span class="s2">"variables"</span><span class="p">:</span> <span class="p">{</span>
<span class="s2">"basefee"</span><span class="p">:</span> <span class="n">update_basefee</span> <span class="c1"># step 3</span>
<span class="p">}</span>
<span class="p">}]</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>We set our initial conditions: an empty demand and basefee starting from the EIP-defined constant <code>INITIAL_BASEFEE</code>.</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">initial_state</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">"basefee"</span><span class="p">:</span> <span class="n">constants</span><span class="p">[</span><span class="s2">"INITIAL_BASEFEE"</span><span class="p">],</span>
<span class="s2">"demand"</span><span class="p">:</span> <span class="p">{}</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>Set up our simulation parameters: for now we will run the simulation for 300 steps (i.e., 300 blocks). Execute the simulation!</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell jp-mod-noOutputs ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="n">blocks</span> <span class="o">=</span> <span class="mi">300</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">Model</span><span class="p">(</span>
<span class="n">initial_state</span><span class="o">=</span><span class="n">initial_state</span><span class="p">,</span>
<span class="n">state_update_blocks</span><span class="o">=</span><span class="n">psub</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">simulation</span> <span class="o">=</span> <span class="n">Simulation</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span> <span class="n">timesteps</span><span class="o">=</span><span class="n">blocks</span><span class="p">,</span> <span class="n">runs</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="n">experiment</span> <span class="o">=</span> <span class="n">Experiment</span><span class="p">([</span><span class="n">simulation</span><span class="p">])</span>
<span class="n">experiment</span><span class="o">.</span><span class="n">engine</span> <span class="o">=</span> <span class="n">Engine</span><span class="p">(</span><span class="n">deepcopy</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">drop_substeps</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">result</span> <span class="o">=</span> <span class="n">experiment</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
</div>
<div class="jp-RenderedHTMLCommon jp-RenderedMarkdown jp-MarkdownOutput " data-mime-type="text/markdown">
<p>OK! Our results are in <code>df</code>, so let's plot the <code>basefee</code> and see how that evolved.</p>
</div><div class="jp-Cell jp-CodeCell jp-Notebook-cell ">
<details>
<summary>Open code input</summary>
<div class="jp-Cell-inputWrapper">
<div class="jp-InputArea jp-Cell-inputArea">
<div></div>
<div class="jp-CodeMirrorEditor jp-Editor jp-InputArea-editor" data-type="inline">
<div class="CodeMirror cm-s-jupyter">
<div class=" highlight hl-ipython3"><pre><span></span><span class="kn">import</span> <span class="nn">seaborn</span> <span class="k">as</span> <span class="nn">sns</span>
<span class="kn">import</span> <span class="nn">matplotlib.pyplot</span> <span class="k">as</span> <span class="nn">plt</span>
<span class="n">sns</span><span class="o">.</span><span class="n">set</span><span class="p">(</span><span class="n">style</span><span class="o">=</span><span class="s2">"whitegrid"</span><span class="p">)</span>
<span class="n">df</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="s1">'timestep'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'basefee'</span><span class="p">])</span>
</pre></div>
</div>
</div>
</div>
</div>
</details>
<div class="jp-Cell-outputWrapper">
<div class="jp-OutputArea jp-Cell-outputArea">
<div class="jp-OutputArea-child">
<div></div>
<div class="jp-RenderedText jp-OutputArea-output jp-OutputArea-executeResult" data-mime-type="text/plain">
<pre><AxesSubplot:xlabel='timestep'></pre>
</div>
</div>
<div class="jp-OutputArea-child">
<div></div>
<div class="jp-RenderedSVG jp-OutputArea-output " data-mime-type="image/svg+xml">
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="277.247813pt" version="1.1" viewBox="0 0 373.99 277.247813" width="373.99pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<metadata>
<rdf:RDF xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<cc:Work>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:date>2021-06-13T11:33:34.366250</dc:date>
<dc:format>image/svg+xml</dc:format>
<dc:creator>
<cc:Agent>
<dc:title>Matplotlib v3.4.2, https://matplotlib.org/</dc:title>
</cc:Agent>
</dc:creator>
</cc:Work>
</rdf:RDF>
</metadata>
<defs>
<style type="text/css">*{stroke-linecap:butt;stroke-linejoin:round;}</style>
</defs>
<g id="figure_1">
<g id="patch_1">
<path d="M 0 277.247813
L 373.99 277.247813
L 373.99 0
L 0 0
z
" style="fill:#ffffff;"/>
</g>
<g id="axes_1">
<g id="patch_2">
<path d="M 31.99 235.513594
L 366.79 235.513594
L 366.79 18.073594
L 31.99 18.073594
z
" style="fill:#ffffff;"/>
</g>
<g id="matplotlib.axis_1">
<g id="xtick_1">
<g id="line2d_1">
<path clip-path="url(#p69e5bbb741)" d="M 47.208182 235.513594
L 47.208182 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_1">
<!-- 0 -->
<g style="fill:#262626;" transform="translate(44.149666 252.887188)scale(0.11 -0.11)">
<defs>
<path d="M 266 2259
Q 266 3072 433 3567
Q 600 4063 929 4331
Q 1259 4600 1759 4600
Q 2128 4600 2406 4451
Q 2684 4303 2865 4023
Q 3047 3744 3150 3342
Q 3253 2941 3253 2259
Q 3253 1453 3087 958
Q 2922 463 2592 192
Q 2263 -78 1759 -78
Q 1097 -78 719 397
Q 266 969 266 2259
z
M 844 2259
Q 844 1131 1108 757
Q 1372 384 1759 384
Q 2147 384 2411 759
Q 2675 1134 2675 2259
Q 2675 3391 2411 3762
Q 2147 4134 1753 4134
Q 1366 4134 1134 3806
Q 844 3388 844 2259
z
" id="ArialMT-30" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_2">
<g id="line2d_2">
<path clip-path="url(#p69e5bbb741)" d="M 97.935455 235.513594
L 97.935455 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_2">
<!-- 50 -->
<g style="fill:#262626;" transform="translate(91.818423 252.887188)scale(0.11 -0.11)">
<defs>
<path d="M 266 1200
L 856 1250
Q 922 819 1161 601
Q 1400 384 1738 384
Q 2144 384 2425 690
Q 2706 997 2706 1503
Q 2706 1984 2436 2262
Q 2166 2541 1728 2541
Q 1456 2541 1237 2417
Q 1019 2294 894 2097
L 366 2166
L 809 4519
L 3088 4519
L 3088 3981
L 1259 3981
L 1013 2750
Q 1425 3038 1878 3038
Q 2478 3038 2890 2622
Q 3303 2206 3303 1553
Q 3303 931 2941 478
Q 2500 -78 1738 -78
Q 1113 -78 717 272
Q 322 622 266 1200
z
" id="ArialMT-35" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-35"/>
<use x="55.615234" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_3">
<g id="line2d_3">
<path clip-path="url(#p69e5bbb741)" d="M 148.662727 235.513594
L 148.662727 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_3">
<!-- 100 -->
<g style="fill:#262626;" transform="translate(139.48718 252.887188)scale(0.11 -0.11)">
<defs>
<path d="M 2384 0
L 1822 0
L 1822 3584
Q 1619 3391 1289 3197
Q 959 3003 697 2906
L 697 3450
Q 1169 3672 1522 3987
Q 1875 4303 2022 4600
L 2384 4600
L 2384 0
z
" id="ArialMT-31" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-31"/>
<use x="55.615234" xlink:href="#ArialMT-30"/>
<use x="111.230469" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_4">
<g id="line2d_4">
<path clip-path="url(#p69e5bbb741)" d="M 199.39 235.513594
L 199.39 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_4">
<!-- 150 -->
<g style="fill:#262626;" transform="translate(190.214453 252.887188)scale(0.11 -0.11)">
<use xlink:href="#ArialMT-31"/>
<use x="55.615234" xlink:href="#ArialMT-35"/>
<use x="111.230469" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_5">
<g id="line2d_5">
<path clip-path="url(#p69e5bbb741)" d="M 250.117273 235.513594
L 250.117273 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_5">
<!-- 200 -->
<g style="fill:#262626;" transform="translate(240.941726 252.887188)scale(0.11 -0.11)">
<defs>
<path d="M 3222 541
L 3222 0
L 194 0
Q 188 203 259 391
Q 375 700 629 1000
Q 884 1300 1366 1694
Q 2113 2306 2375 2664
Q 2638 3022 2638 3341
Q 2638 3675 2398 3904
Q 2159 4134 1775 4134
Q 1369 4134 1125 3890
Q 881 3647 878 3216
L 300 3275
Q 359 3922 746 4261
Q 1134 4600 1788 4600
Q 2447 4600 2831 4234
Q 3216 3869 3216 3328
Q 3216 3053 3103 2787
Q 2991 2522 2730 2228
Q 2469 1934 1863 1422
Q 1356 997 1212 845
Q 1069 694 975 541
L 3222 541
z
" id="ArialMT-32" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-32"/>
<use x="55.615234" xlink:href="#ArialMT-30"/>
<use x="111.230469" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_6">
<g id="line2d_6">
<path clip-path="url(#p69e5bbb741)" d="M 300.844545 235.513594
L 300.844545 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_6">
<!-- 250 -->
<g style="fill:#262626;" transform="translate(291.668999 252.887188)scale(0.11 -0.11)">
<use xlink:href="#ArialMT-32"/>
<use x="55.615234" xlink:href="#ArialMT-35"/>
<use x="111.230469" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="xtick_7">
<g id="line2d_7">
<path clip-path="url(#p69e5bbb741)" d="M 351.571818 235.513594
L 351.571818 18.073594
" style="fill:none;stroke:#cccccc;stroke-linecap:round;"/>
</g>
<g id="text_7">
<!-- 300 -->
<g style="fill:#262626;" transform="translate(342.396271 252.887188)scale(0.11 -0.11)">
<defs>
<path d="M 269 1209
L 831 1284
Q 928 806 1161 595
Q 1394 384 1728 384
Q 2125 384 2398 659
Q 2672 934 2672 1341
Q 2672 1728 2419 1979
Q 2166 2231 1775 2231
Q 1616 2231 1378 2169
L 1441 2663
Q 1497 2656 1531 2656
Q 1891 2656 2178 2843
Q 2466 3031 2466 3422
Q 2466 3731 2256 3934
Q 2047 4138 1716 4138
Q 1388 4138 1169 3931
Q 950 3725 888 3313
L 325 3413
Q 428 3978 793 4289
Q 1159 4600 1703 4600
Q 2078 4600 2393 4439
Q 2709 4278 2876 4000
Q 3044 3722 3044 3409
Q 3044 3113 2884 2869
Q 2725 2625 2413 2481
Q 2819 2388 3044 2092
Q 3269 1797 3269 1353
Q 3269 753 2831 336
Q 2394 -81 1725 -81
Q 1122 -81 723 278
Q 325 638 269 1209
z
" id="ArialMT-33" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-33"/>
<use x="55.615234" xlink:href="#ArialMT-30"/>
<use x="111.230469" xlink:href="#ArialMT-30"/>
</g>
</g>
</g>
<g id="text_8">
<!-- timestep -->
<g style="fill:#262626;" transform="translate(176.715625 267.662813)scale(0.12 -0.12)">
<defs>
<path d="M 1650 503
L 1731 6
Q 1494 -44 1306 -44
Q 1000 -44 831 53
Q 663 150 594 308
Q 525 466 525 972
L 525 2881
L 113 2881
L 113 3319
L 525 3319
L 525 4141
L 1084 4478
L 1084 3319
L 1650 3319
L 1650 2881
L 1084 2881
L 1084 941
Q 1084 700 1114 631
Q 1144 563 1211 522
Q 1278 481 1403 481
Q 1497 481 1650 503
z
" id="ArialMT-74" transform="scale(0.015625)"/>
<path d="M 425 3934
L 425 4581
L 988 4581
L 988 3934
L 425 3934
z
M 425 0
L 425 3319
L 988 3319
L 988 0
L 425 0
z
" id="ArialMT-69" transform="scale(0.015625)"/>
<path d="M 422 0
L 422 3319
L 925 3319
L 925 2853
Q 1081 3097 1340 3245
Q 1600 3394 1931 3394
Q 2300 3394 2536 3241
Q 2772 3088 2869 2813
Q 3263 3394 3894 3394
Q 4388 3394 4653 3120
Q 4919 2847 4919 2278
L 4919 0
L 4359 0
L 4359 2091
Q 4359 2428 4304 2576
Q 4250 2725 4106 2815
Q 3963 2906 3769 2906
Q 3419 2906 3187 2673
Q 2956 2441 2956 1928
L 2956 0
L 2394 0
L 2394 2156
Q 2394 2531 2256 2718
Q 2119 2906 1806 2906
Q 1569 2906 1367 2781
Q 1166 2656 1075 2415
Q 984 2175 984 1722
L 984 0
L 422 0
z
" id="ArialMT-6d" transform="scale(0.015625)"/>
<path d="M 2694 1069
L 3275 997
Q 3138 488 2766 206
Q 2394 -75 1816 -75
Q 1088 -75 661 373
Q 234 822 234 1631
Q 234 2469 665 2931
Q 1097 3394 1784 3394
Q 2450 3394 2872 2941
Q 3294 2488 3294 1666
Q 3294 1616 3291 1516
L 816 1516
Q 847 969 1125 678
Q 1403 388 1819 388
Q 2128 388 2347 550
Q 2566 713 2694 1069
z
M 847 1978
L 2700 1978
Q 2663 2397 2488 2606
Q 2219 2931 1791 2931
Q 1403 2931 1139 2672
Q 875 2413 847 1978
z
" id="ArialMT-65" transform="scale(0.015625)"/>
<path d="M 197 991
L 753 1078
Q 800 744 1014 566
Q 1228 388 1613 388
Q 2000 388 2187 545
Q 2375 703 2375 916
Q 2375 1106 2209 1216
Q 2094 1291 1634 1406
Q 1016 1563 777 1677
Q 538 1791 414 1992
Q 291 2194 291 2438
Q 291 2659 392 2848
Q 494 3038 669 3163
Q 800 3259 1026 3326
Q 1253 3394 1513 3394
Q 1903 3394 2198 3281
Q 2494 3169 2634 2976
Q 2775 2784 2828 2463
L 2278 2388
Q 2241 2644 2061 2787
Q 1881 2931 1553 2931
Q 1166 2931 1000 2803
Q 834 2675 834 2503
Q 834 2394 903 2306
Q 972 2216 1119 2156
Q 1203 2125 1616 2013
Q 2213 1853 2448 1751
Q 2684 1650 2818 1456
Q 2953 1263 2953 975
Q 2953 694 2789 445
Q 2625 197 2315 61
Q 2006 -75 1616 -75
Q 969 -75 630 194
Q 291 463 197 991
z
" id="ArialMT-73" transform="scale(0.015625)"/>
<path d="M 422 -1272
L 422 3319
L 934 3319
L 934 2888
Q 1116 3141 1344 3267
Q 1572 3394 1897 3394
Q 2322 3394 2647 3175
Q 2972 2956 3137 2557
Q 3303 2159 3303 1684
Q 3303 1175 3120 767
Q 2938 359 2589 142
Q 2241 -75 1856 -75
Q 1575 -75 1351 44
Q 1128 163 984 344
L 984 -1272
L 422 -1272
z
M 931 1641
Q 931 1000 1190 694
Q 1450 388 1819 388
Q 2194 388 2461 705
Q 2728 1022 2728 1688
Q 2728 2322 2467 2637
Q 2206 2953 1844 2953
Q 1484 2953 1207 2617
Q 931 2281 931 1641
z
" id="ArialMT-70" transform="scale(0.015625)"/>
</defs>
<use xlink:href="#ArialMT-74"/>
<use x="27.783203" xlink:href="#ArialMT-69"/>
<use x="50" xlink:href="#ArialMT-6d"/>
<use x="133.300781" xlink:href="#ArialMT-65"/>
<use x="188.916016" xlink:href="#ArialMT-73"/>