<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Whales are Fish</title>
    <link rel="self" type="application/atom+xml" href="https://fvictorio.github.io/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://fvictorio.github.io/"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2025-10-30T00:00:00+00:00</updated>
    <id>https://fvictorio.github.io/atom.xml</id>
    <entry xml:lang="en">
        <title>An underqualified reading list about the transformer architecture</title>
        <published>2025-10-30T00:00:00+00:00</published>
        <updated>2025-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://fvictorio.github.io/posts/underqualified-transformer-reading-list/"/>
        <id>https://fvictorio.github.io/posts/underqualified-transformer-reading-list/</id>
        
        <content type="html" xml:base="https://fvictorio.github.io/posts/underqualified-transformer-reading-list/">&lt;p&gt;When I see a list of learning resources, I assume that whoever curated it knows much more about the topic than what I’ll learn. So you wouldn’t be blamed for thinking that I have read 100x the amount of things about the transformer architecture than what I’m sharing here. In reality, that multiplier is shamefully close to 1x. Put another way: I have no idea what I’m talking about.&lt;&#x2F;p&gt;
&lt;p&gt;But I think this list can be useful anyway, because it has a couple of somewhat idiosyncratic goals: &lt;strong&gt;conceptual understanding&lt;&#x2F;strong&gt; and &lt;strong&gt;historical perspective&lt;&#x2F;strong&gt;. By conceptual understanding I just mean having a slightly better mental model of what’s going on under the hood when you use a tool like ChatGPT. And by historical perspective I mean understanding how this architecture fits in the bigger narrative of artificial intelligence research.&lt;&#x2F;p&gt;
&lt;p&gt;Having those goals means that this list is not &lt;em&gt;practical&lt;&#x2F;em&gt;: there’s nothing about prompt engineering or how to use an API, let alone how to implement or train an LLM, or even run one locally. There are also no philosophical musings like “well, but is this &lt;em&gt;really&lt;&#x2F;em&gt; thinking?” nor, God forbid, any ethical discussions about alignment or whatever. But if you want to get a basic understanding of how transformers work and have a (short, incomplete, probably wrong) narrative of how they came about, then I’d say this post is for you.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;pre-requisites&quot;&gt;Pre-requisites&lt;&#x2F;h1&gt;
&lt;p&gt;I’m assuming you have some understanding of how neural networks work. If the following two sentences make sense, then I’d say you can easily read everything I’m recommending in this list:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The weights of a neural network are set during training, using training data and the backpropagation algorithm.&lt;&#x2F;li&gt;
&lt;li&gt;A forward pass in a neural network is mainly just a bunch of matrix multiplications.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If (like me) you kind of understand them but it’s been a while since you’ve used this stuff, then the first four chapters of &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=aircAruvnKk&amp;amp;list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi&amp;amp;ab_channel=3Blue1Brown&quot;&gt;3blue1brown’s series on deep learning&lt;&#x2F;a&gt; are a good refresher. They might also work as an introduction if you are starting from scratch, but I can’t say for sure since that wasn’t the case for me.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-list&quot;&gt;The list&lt;&#x2F;h1&gt;
&lt;p&gt;I’m going to sort this list in the order I think makes the most sense. In addition to that, each section is grouped by a topic and driven by a question. To be honest, I didn’t read the things here in the order I’m using; it was way more chaotic. But this is how I would explain it to someone else.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-bitter-lesson&quot;&gt;The bitter lesson&lt;&#x2F;h2&gt;
&lt;p&gt;There was a comment about transformers that I kept hearing: that one reason they were revolutionary was that they were very parallelizable. This meant that they could be trained faster and therefore use more data during training. And while it makes sense that this was a big deal, I was still intrigued: how something as prosaic as parallelizability could have unleashed the current AI boom? In reality this is only part of the explanation, but still.&lt;&#x2F;p&gt;
&lt;p&gt;Turns out there is a perfect answer to that question: &lt;a href=&quot;http:&#x2F;&#x2F;www.incompleteideas.net&#x2F;IncIdeas&#x2F;BitterLesson.html&quot;&gt;The Bitter Lesson&lt;&#x2F;a&gt;, by Richard Sutton.&lt;&#x2F;p&gt;
&lt;p&gt;This is apparently a classic within the AI community, and I can see why. It’s powerful, packed with wisdom, persuasively argued and, on top of all that, it’s very short. Read it, re-read it, and read it again after finishing this list. It’s fantastic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;recurrent-neural-networks&quot;&gt;Recurrent Neural Networks&lt;&#x2F;h2&gt;
&lt;p&gt;Ok, so the transformer is more parallelizable, and that matters. But more parallelizable than &lt;em&gt;what&lt;&#x2F;em&gt;? The most common comparison is with Recurrent Neural Networks (RNNs), which apparently were the state of the art before transformers stole the spotlight.&lt;&#x2F;p&gt;
&lt;p&gt;Do you need to understand RNNs to understand transformers? Not at all. But I’m including this section anyway for two reasons. One is that they help with the historical perspective, which is one of the goals of this list. But also because the two resources I have to share are excellent. They were written by people who really know what they are talking about, and who love teaching.&lt;&#x2F;p&gt;
&lt;p&gt;The first is &lt;a href=&quot;https:&#x2F;&#x2F;colah.github.io&#x2F;posts&#x2F;2015-08-Understanding-LSTMs&#x2F;&quot;&gt;Understanding LSTMs&lt;&#x2F;a&gt;, by Chris Olah&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. If you are not that interested in the topic, you can read just the first two sections (“Recurrent Neural Networks” and “The Problem of Long-Term Dependencies”), and the Conclusion at the end. But I’d still recommend reading the whole thing, because the explanation is great and LSTMs (a type of RNN) are quite interesting.&lt;&#x2F;p&gt;
&lt;p&gt;The second RNN-related resource is &lt;a href=&quot;https:&#x2F;&#x2F;karpathy.github.io&#x2F;2015&#x2F;05&#x2F;21&#x2F;rnn-effectiveness&#x2F;&quot;&gt;The Unreasonable Effectiveness of Recurrent Neural Networks&lt;&#x2F;a&gt;, by Andrej Karpathy&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. As with the previous article, you can focus on the beginning and the conclusion, but all of it is worth reading.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attention&quot;&gt;Attention&lt;&#x2F;h2&gt;
&lt;p&gt;The two articles about RNNs I recommended above make similar remarks in their closing sections (emphasis mine):&lt;&#x2F;p&gt;
&lt;p&gt;Colah:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;LSTMs were a big step in what we can accomplish with RNNs. It’s natural to wonder: is there another big step? A common opinion among researchers is: “Yes! There is a next step and it’s &lt;strong&gt;attention&lt;&#x2F;strong&gt;!&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Karpathy:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The concept of &lt;strong&gt;attention&lt;&#x2F;strong&gt; is the most interesting recent architectural innovation in neural networks.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;What is this curiously named concept?&lt;&#x2F;p&gt;
&lt;p&gt;One good first explanation is &lt;a href=&quot;https:&#x2F;&#x2F;jalammar.github.io&#x2F;visualizing-neural-machine-translation-mechanics-of-seq2seq-models-with-attention&#x2F;&quot;&gt;Mechanics of Seq2seq Models With Attention&lt;&#x2F;a&gt;, by Jay Alammar. It explains attention in the context of RNNs, which makes the article a bit dated. But at the same time, that’s a good thing, because it fits with the simplified narrative we are building.&lt;&#x2F;p&gt;
&lt;p&gt;There’s much more to say about the attention mechanism, but it’s time to jump to what we are really interested in.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;transformers&quot;&gt;Transformers&lt;&#x2F;h2&gt;
&lt;p&gt;I had heard the terms “attention” and “transformers” together a lot. I had also heard about the legendary paper “Attention is all you need”. In my fuzzy understanding, I coupled these two concepts, thinking that transformers and attention were kind of synonyms. But as we saw in the previous sections, that’s not the case, and people were talking about attention years before this paper was published.&lt;&#x2F;p&gt;
&lt;p&gt;Besides, the title of the paper is very self-descriptive! It’s not called “Introducing the attention mechanism”. The main idea of the paper is that you can do a lot with &lt;em&gt;only&lt;&#x2F;em&gt; that mechanism, implying that it already existed.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So we have a basic understanding of what the attention mechanism is, and the vague idea that a “transformer” is an architecture that relies a lot on that mechanism. A good next step is &lt;a href=&quot;https:&#x2F;&#x2F;jalammar.github.io&#x2F;illustrated-transformer&#x2F;&quot;&gt;The Illustrated Transformer&lt;&#x2F;a&gt;, also by Jay Alammar. As with the attention explainer, this one is outdated (more on this soon). But, again, this is helpful to understand how things developed historically. Even if the encoder-decoder architecture explained in the article is (I’ve been told) not used anymore, it shows how transformers evolved from the “sequence-to-sequence with RNNs” world, which is nice.&lt;&#x2F;p&gt;
&lt;p&gt;If after reading The Illustrated Transformer you feel like saying “great, I understand transformers now, I can stop here and go brag about it”, then that’s it, at least for this section. But I personally think that deep topics are best understood through multiple perspectives, so I’ll share two resources more.&lt;&#x2F;p&gt;
&lt;p&gt;One is the &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=wjZofJX0v4M&amp;amp;list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi&amp;amp;index=6&quot;&gt;rest of the 3blue1brown series on Deep Learning&lt;&#x2F;a&gt;. As I mentioned in the &lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;underqualified-transformer-reading-list&#x2F;#pre-requisites&quot;&gt;Pre-requisites&lt;&#x2F;a&gt; section, the first four chapters are good for learning&#x2F;reviewing classical neural networks; the rest of the series focuses on transformers and LLMs.&lt;&#x2F;p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;Aside&lt;&#x2F;b&gt;: A brief comment about learning from videos&lt;&#x2F;summary&gt;
&lt;p style=&quot;margin-left:2em;&quot;&gt;I have to say I&#x27;m a bit skeptical of video explanations, unless you have the discipline to watch them in a very active way: pausing to think, taking notes, re-watching parts you didn&#x27;t fully understand. But I personally find that the medium is not conducive to that. Your experience can be different, of course, but I myself only use videos to get things explained in a different way, or when I&#x27;m only interested in getting a quick, shallow understanding.&lt;&#x2F;p&gt;
&lt;&#x2F;details&gt;
&lt;p&gt;The other resource happens to be my favorite article in this list: &lt;a href=&quot;https:&#x2F;&#x2F;peterbloem.nl&#x2F;blog&#x2F;transformers&quot;&gt;Transformers from scratch&lt;&#x2F;a&gt;, by Peter Bloem. This is a more rigorous and modern explanation, but that’s not the reason I like it so much. It’s because it approaches things in the way I like to teach and learn: start with the essence of things, and gradually add complexity as needed. Take key&#x2F;query&#x2F;value vectors, for example. Other explainers will mention them in a way that feels almost arbitrary. Here, on the other hand, they are just additional tricks on top of the core idea (quick question: why are there three kinds of these vectors? Why not four? While the article doesn’t spell it out, you’ll be able to answer this anyway). I have to admit that I only skimmed the code sections, even if I agree in principle with the idea that “What I cannot create, I do not understand”. It just wasn’t part of my learning goal.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;large-language-models&quot;&gt;Large Language Models&lt;&#x2F;h2&gt;
&lt;p&gt;While up to this point we’ve only talked about neural networks and attention mechanisms and transformers, let’s not pretend we aren’t learning these things because of our new hallucinating overlords. But there’s a reason I haven’t mentioned LLMs so far. Just as it’s easy to conflate transformers with the attention mechanism, even if they are conceptually separate things, it’s also easy to think that transformers and LLMs are somehow equivalent. And that’s not the case, in either direction. An LLM doesn’t &lt;em&gt;have&lt;&#x2F;em&gt; to use the transformer architecture (although all of the big ones do today). To see how this is the case, watch &lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=OFS90-FX6pg&quot;&gt;The 35-Year History of LLMs&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-4-1&quot;&gt;&lt;a href=&quot;#fn-4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Even more importantly, the transformer architecture can be used for many other things. Quoting the definition of transformers from “Transformers from Scratch”:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any architecture designed to process a connected set of units—such as the tokens in a sequence or the pixels in an image—where the only interaction between units is through self-attention.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In other words, if your input is “a connected set of units” (a text, an image, a non-linear logographic alien language), then using transformers is a good bet.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;closing-words&quot;&gt;Closing words&lt;&#x2F;h1&gt;
&lt;p&gt;What’s next? I don’t know! As I said in the introduction, I haven’t read much more on the topic than what I shared. But, true to the spirit of talking without knowing, here are some possible next steps:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1706.03762&quot;&gt;Attention is all you need&lt;&#x2F;a&gt; paper. Obviously outdated, but just skimming it is interesting for historical reasons. There’s a mix of the authors knowing that this is really cool with the fact that they obviously couldn’t predict what they were unleashing. It’s also interesting how focused it is on language translation, given the much broader applicability that transformers have shown.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=kCc8FmEb1nY&quot;&gt;Let’s build GPT: from scratch, in code, spelled out&lt;&#x2F;a&gt;, by Andrej Karpathy. I admit I haven’t watched this one, but I’ve seen it mentioned multiple times as a great resource.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=kPGTx4wcm_w&quot;&gt;Developing an LLM: Building, Training, Finetuning&lt;&#x2F;a&gt;. A video about the real-world details of building an LLM. I think this is the least well-known resource in this list, and the most advanced, but I think it’s a good complement to the rest of the material given that it’s very grounded in reality.&lt;&#x2F;li&gt;
&lt;li&gt;Go and re-read &lt;a href=&quot;http:&#x2F;&#x2F;www.incompleteideas.net&#x2F;IncIdeas&#x2F;BitterLesson.html&quot;&gt;The Bitter Lesson&lt;&#x2F;a&gt; again.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;hr &#x2F;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;One of the founders of Anthropic. He also worked at OpenAI and Google Brain. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;Famous &lt;a href=&quot;http:&#x2F;&#x2F;badmephisto.com&#x2F;&quot;&gt;speedcubing influencer&lt;&#x2F;a&gt;. Also a founding member of OpenAI and former Director of AI at Tesla. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;This reminds me of a passage in the classic &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;How_to_Read_a_Book&quot;&gt;&lt;em&gt;How to read a book&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; about how we don’t pay enough attention to titles. The authors say this with respect to Gibbon’s &lt;em&gt;The Decline and Fall of the Roman Empire&lt;&#x2F;em&gt;: «Nevertheless, when we asked the same twenty-five well-read people why the first chapter is called “The Extent and Military Force of the Empire in the Age of the Antonines,&quot; they had no idea. [...] Unconsciously, they had translated “decline and fall” into “rise and fall.&quot; They were puzzled because there was no discussion of the Roman Republic, which ended a century and a half before the Age of the Antonines. If they had read the title carefully they could have assumed that the Age of the Antonines was the high point of the Empire, even if they had not known it before. Reading the title, in other words, could have given them essential information about the book before they started to read it.» &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-4&quot;&gt;
&lt;p&gt;Apparently the title of the video has been changed to “The Origin of ChatGPT”, for what I guess are obvious reasons. &lt;a href=&quot;#fr-4-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>You and Your Shell</title>
        <published>2023-09-24T00:00:00+00:00</published>
        <updated>2023-09-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://fvictorio.github.io/posts/you-and-your-shell/"/>
        <id>https://fvictorio.github.io/posts/you-and-your-shell/</id>
        
        <content type="html" xml:base="https://fvictorio.github.io/posts/you-and-your-shell/">&lt;p&gt;This article is my attempt to explain what is a shell and what it does. My goal is for you to build a useful mental model of what’s going on under the hood when you open a terminal, paste some command, and hope that it doesn’t erase all your terrible, embarrasing, hidden sci-fi poems.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;is-this-for-you&quot;&gt;Is this for you?&lt;&#x2F;h1&gt;
&lt;p&gt;I think you won’t get much from this article if you can answer these questions without even blinking:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What is the difference between &lt;code&gt;echo foo&lt;&#x2F;code&gt; and &lt;code&gt;echo &#x27;foo&#x27;&lt;&#x2F;code&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;What’s going on when you do &lt;code&gt;DEBUG=&#x27;*&#x27; some-command&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;What’s the difference between a program and a shell built-in? Why do we have both?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But you may still want to jump directly to &lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#examples&quot;&gt;the examples&lt;&#x2F;a&gt;. If you find any of them surprising, then maybe there’s something useful for you here!&lt;&#x2F;p&gt;
&lt;h1 id=&quot;contents&quot;&gt;Contents&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#what-is-a-shell&quot;&gt;What is a shell?&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#running-programs&quot;&gt;Running programs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#the-worst-shell-in-the-world&quot;&gt;The worst shell in the world&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#finding-programs&quot;&gt;Finding programs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#parsing-arguments&quot;&gt;Parsing arguments&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#globs&quot;&gt;Globs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#quotes&quot;&gt;Quotes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#environment-variables&quot;&gt;Environment variables&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#built-in-commands&quot;&gt;Built-in commands&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#examples&quot;&gt;Examples!&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#example-1-the-separator&quot;&gt;Example 1: The &lt;code&gt;--&lt;&#x2F;code&gt; separator&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#example-2-escaping-quotes&quot;&gt;Example 2: Escaping quotes&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#example-3-conditions-in-bash-programming&quot;&gt;Example 3: Conditions in bash programming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#clarifications&quot;&gt;Clarifications&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;you-and-your-shell&#x2F;#further-reading&quot;&gt;Further reading&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;what-is-a-shell&quot;&gt;What is a shell?&lt;&#x2F;h1&gt;
&lt;p&gt;My favorite definition comes from the classic &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;The_Unix_Programming_Environment&quot;&gt;The UNIX Programming Environment&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[The shell is] the program that interprets your requests to run programs.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This short sentence tells us a lot:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;First, a shell is just a program. &lt;code&gt;bash&lt;&#x2F;code&gt;, &lt;code&gt;zsh&lt;&#x2F;code&gt; and &lt;code&gt;fish&lt;&#x2F;code&gt; are all different programs that function as shells.&lt;&#x2F;li&gt;
&lt;li&gt;Second, a shell interprets requests. You use a specific language for these requests, even if you are not aware of it.&lt;&#x2F;li&gt;
&lt;li&gt;Finally, a shell is used to run programs. You can do other things with it, but that’s its main purpose.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let’s explore this definition in more detail.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;running-programs&quot;&gt;Running programs&lt;&#x2F;h2&gt;
&lt;p&gt;The first thing we need to understand is that a program is always started from another program.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; Who started that other program, you might ask? Well, of course: a third program. And who started that one? Yet another program. But who...? I don’t know, &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Init&quot;&gt;a turtle or something&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The details of what exactly a program does to start another one are not relevant for our purposes. We can just assume that there is a function that looks like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;function &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;runProgram&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;arguments&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;[],
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;environmentVariables&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;?: &lt;&#x2F;span&gt;&lt;span&gt;Record&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a crude simplification, but it will do. At its core, starting a program requires its path in the filesystem and a list of arguments. We can also optionally pass a dictionary of environment variables.&lt;&#x2F;p&gt;
&lt;p&gt;With this function and our previous definition, we can try to write a very simple and useless shell.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-worst-shell-in-the-world&quot;&gt;The worst shell in the world&lt;&#x2F;h2&gt;
&lt;p&gt;Since we defined a shell as a program that interprets requests to run programs and assumed we have a &lt;code&gt;runProgram&lt;&#x2F;code&gt; function, we can write an extremely simple shell that just runs whatever program is passed to it:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;pathToProgram &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;readLine&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;runProgram&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span&gt;, []);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would be extremely useless, but it does the job. You input a path to the program you want to run, our shitty shell interprets your request verbatim, and that’s it. But a real shell does much more than that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-programs&quot;&gt;Finding programs&lt;&#x2F;h2&gt;
&lt;p&gt;When you want to run the &lt;code&gt;df&lt;&#x2F;code&gt; program to see if you have enough space to keep &lt;del&gt;downloading&lt;&#x2F;del&gt; buying movies, you don’t write &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;df&lt;&#x2F;code&gt;, you just write &lt;code&gt;df&lt;&#x2F;code&gt;. This wouldn’t work on our dumb implementation, but it does in any real shell.&lt;&#x2F;p&gt;
&lt;p&gt;The reason this works is that the shell will check a list of pre-defined directories to see if any of them contains a program with that name. You probably already know that this list is in the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;PATH_(variable)&quot;&gt;&lt;code&gt;PATH&lt;&#x2F;code&gt; environment variable&lt;&#x2F;a&gt;. We can easily add this feature to our previous snippet, especially if we assume that we have more magic functions available:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;program &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;readLine&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;pathToProgram &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;findProgram&lt;&#x2F;span&gt;&lt;span&gt;(process.env.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;program&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;runProgram&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span&gt;, []);
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;`No program named &amp;#39;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;program&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;}&amp;#39; was found`&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;Now&lt;&#x2F;em&gt; we are doing some interpretation.&lt;&#x2F;p&gt;
&lt;p&gt;But what if we want to pass some arguments to a program? If we run &lt;code&gt;rm Titanic.mkv&lt;&#x2F;code&gt; we’ll get this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;No program named &amp;#39;rm Titanic.mkv&amp;#39; was found
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Which makes sense! We are taking the full line and interpreting it as a program name. Whitespace is not special, and neither are you.&lt;&#x2F;p&gt;
&lt;p&gt;What we need here is some more of that sweet &lt;em&gt;interpretation&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;parsing-arguments&quot;&gt;Parsing arguments&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s update our shell to interpret whitespace as a separator between the name of the program and the arguments:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6e9cbe;&quot;&gt;true&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;line &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;readLine&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;program&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;line&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d9cbe;&quot;&gt;\s&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;g&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;pathToProgram &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;findProgram&lt;&#x2F;span&gt;&lt;span&gt;(process.env.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;PATH&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;program&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;runProgram&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;pathToProgram&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;error&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;`No program named &amp;#39;${&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;program&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;}&amp;#39; was found`&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If this code actually worked and we ran &lt;code&gt;rm Titanic.mkv&lt;&#x2F;code&gt; on it, it would actually delete the file. Probably. In any case, the takeaway is that we are doing a more complex interpretation of the command we receive. The command is still just a string, but we are starting to parse it in a somewhat interesting way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;globs&quot;&gt;Globs&lt;&#x2F;h2&gt;
&lt;p&gt;What if you want to remove all the files that end in &lt;code&gt;.mkv&lt;&#x2F;code&gt; in a directory? It’s easy with our shell: you just run &lt;code&gt;ls&lt;&#x2F;code&gt;, then write &lt;code&gt;rm &lt;&#x2F;code&gt;, and then manually add all the files that end with that extension. I’m sure you won’t make any typos.&lt;&#x2F;p&gt;
&lt;p&gt;If you don’t like typing, then there are some ways this could be automated. Maybe you could use a version of &lt;code&gt;rm&lt;&#x2F;code&gt; that, instead of a list of files, receives an extension as its argument and removes all the files with that extension. Or perhaps you could have one program that writes all the files with some extension to a file, and then pass that file to another program which consumes it and removes all the files pointed by it...&lt;&#x2F;p&gt;
&lt;p&gt;...or you could just add a new feature to the shell. You could say that, if the shell finds something like &lt;code&gt;*.mkv&lt;&#x2F;code&gt;, then it will interpret it as “all the files in the current directory that end in &lt;code&gt;mkv&lt;&#x2F;code&gt;&quot;. This is called &lt;a href=&quot;https:&#x2F;&#x2F;tldp.org&#x2F;LDP&#x2F;abs&#x2F;html&#x2F;globbingref.html&quot;&gt;glob expansion or globbing&lt;&#x2F;a&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Glob_(programming)&quot;&gt;Globs&lt;&#x2F;a&gt; are like regular expressions, but worse, or better; it’s hard to say.&lt;&#x2F;p&gt;
&lt;p&gt;The important part here, and probably the most important part of this article, is that &lt;strong&gt;this expansion is performed by the shell!&lt;&#x2F;strong&gt; This is quite easy to check by writing a program that just prints its arguments. With Node.js, you can do something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;&#x2F;&#x2F; index.js
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;arguments &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;process.argv.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;slice&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a5c261;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#86c20e;&quot;&gt;JSON&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;stringify&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;arguments&lt;&#x2F;span&gt;&lt;span&gt;));
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you run &lt;code&gt;node index.js 1 2 foo&lt;&#x2F;code&gt;, you will get the list &lt;code&gt;[&quot;1&quot;,&quot;2&quot;,&quot;foo&quot;]&lt;&#x2F;code&gt;. (Don’t pay too much attention to the &lt;code&gt;.slice(2)&lt;&#x2F;code&gt; part, this just avoids printing the paths to the node binary and the script, which are included in the arguments list for what I’m sure are very good reasons.)&lt;&#x2F;p&gt;
&lt;p&gt;If you now create some files:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;txt&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-txt &quot;&gt;&lt;code class=&quot;language-txt&quot; data-lang=&quot;txt&quot;&gt;&lt;span&gt;$ touch a.txt b.txt c.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And then run &lt;code&gt;node index.js *.txt&lt;&#x2F;code&gt;, the program will print &lt;code&gt;[&quot;a.txt&quot;,&quot;b.txt&quot;,&quot;c.txt&quot;]&lt;&#x2F;code&gt;, not &lt;code&gt;[&quot;*.txt&quot;]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Things like &lt;code&gt;*&lt;&#x2F;code&gt; are called &lt;strong&gt;metacharacters&lt;&#x2F;strong&gt;. These are characters that receive a special treatment by the shell. There are a lot of these, like &lt;code&gt;?&lt;&#x2F;code&gt;, &lt;code&gt;|&lt;&#x2F;code&gt;, &lt;code&gt;&amp;lt;&lt;&#x2F;code&gt; and &lt;code&gt;&amp;gt;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But now you, being a smart and curious person, are wondering: “what if I actually want to pass &lt;code&gt;*.txt&lt;&#x2F;code&gt; as an argument to a program, for my own devious purposes?&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quotes&quot;&gt;Quotes&lt;&#x2F;h2&gt;
&lt;p&gt;This is one of the things you might do without fully understanding. You run something in the shell; it doesn’t work and you get a scary error message. You try adding some quotes. Now it works. Success! But what did actually happen?&lt;&#x2F;p&gt;
&lt;p&gt;Here I’m going to quote from &lt;em&gt;The UNIX Programming Environment&lt;&#x2F;em&gt; again.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Given the number of shell metacharacters, there has to be some way to say to the shell, “Leave it alone”. The easiest and best way to protect special characters from being interpreted is to enclose them in single quote characters:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo &amp;#39;***&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;***
&lt;&#x2F;span&gt;&lt;span&gt;$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Honestly, you should just close this tab and go read Chapter 3 from that book. It’s so good.&lt;&#x2F;p&gt;
&lt;p&gt;But yes: you use single or double quotes to escape metacharacters. Single quotes escape everything, double quotes allows certain expansions within them. I think a good rule of thumb is “always use single quotes unless you know what you’re doing”.&lt;&#x2F;p&gt;
&lt;p&gt;So, going back to the question in the previous section, if you want to literally pass &lt;code&gt;*.txt&lt;&#x2F;code&gt; as an argument to a program, you can do:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ rm &amp;#39;*.txt&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And if you have a file that is literally named &lt;code&gt;*.txt&lt;&#x2F;code&gt; then 1) you are a monster and 2) it will be removed.&lt;&#x2F;p&gt;
&lt;p&gt;You can also try this with the little script we wrote before:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ node index.js &amp;#39;*.txt&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;[&amp;quot;*.txt&amp;quot;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;environment-variables&quot;&gt;Environment variables&lt;&#x2F;h2&gt;
&lt;p&gt;So far, we’ve called our &lt;code&gt;runProgram&lt;&#x2F;code&gt; function without passing any environment variables. The default behavior in this case is that the environment of the parent process will be passed to the child process (or maybe some of them are changed? I’m fuzzy on the details here).&lt;&#x2F;p&gt;
&lt;p&gt;What if you want to run a program with some specific environment variables? Most shells let you do this with a special syntax. In bash&#x2F;zsh&#x2F;fish, for example, you can do:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ FOO=1 BAR=2 program arg1 arg2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is, you can prepend the program name with a list of environment variables. As before, it’s easy to write a little script to test this out:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;typescript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-typescript &quot;&gt;&lt;code class=&quot;language-typescript&quot; data-lang=&quot;typescript&quot;&gt;&lt;span style=&quot;color:#95815e;&quot;&gt;&#x2F;&#x2F; index.js
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;console&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;log&lt;&#x2F;span&gt;&lt;span&gt;(process.env.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;FOO&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Running &lt;code&gt;node index.js&lt;&#x2F;code&gt; will print &lt;code&gt;undefined&lt;&#x2F;code&gt; but running &lt;code&gt;FOO=1 node index.js&lt;&#x2F;code&gt; will print &lt;code&gt;1&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is an alternative way to do this that you’ve surely seen before, but which is not exactly equivalent:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ export FOO=1
&lt;&#x2F;span&gt;&lt;span&gt;$ node index.js
&lt;&#x2F;span&gt;&lt;span&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The difference here is that &lt;code&gt;export FOO=1&lt;&#x2F;code&gt; is modifying the environment of the shell, which is then passed down to our script. This is persistent: if we run &lt;code&gt;node index.js&lt;&#x2F;code&gt; a second time in the same shell session, it will print 1 again. But if we do that with the previous version (assuming a fresh shell instance), it won’t:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ FOO=1 node index.js
&lt;&#x2F;span&gt;&lt;span&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;$ node index.js
&lt;&#x2F;span&gt;&lt;span&gt;undefined
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;built-in-commands&quot;&gt;Built-in commands&lt;&#x2F;h2&gt;
&lt;p&gt;The most interesting part of the previous section is &lt;code&gt;export FOO=1&lt;&#x2F;code&gt;. This is an example of running a command in the shell that &lt;em&gt;doesn’t&lt;&#x2F;em&gt; execute a program. &lt;code&gt;export&lt;&#x2F;code&gt; here is what’s called a &lt;em&gt;built-in command&lt;&#x2F;em&gt; of the shell.&lt;&#x2F;p&gt;
&lt;p&gt;When you run things like &lt;code&gt;df&lt;&#x2F;code&gt;, &lt;code&gt;rm&lt;&#x2F;code&gt;, &lt;code&gt;vim&lt;&#x2F;code&gt; or whatever, there is an actual file in your disk with the code for that program. You can use &lt;code&gt;whereis&lt;&#x2F;code&gt; to find the path to that file:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ whereis df
&lt;&#x2F;span&gt;&lt;span&gt;df: &#x2F;usr&#x2F;bin&#x2F;df &#x2F;usr&#x2F;share&#x2F;man&#x2F;man1&#x2F;df.1.gz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But if you do the same with a built-in, you get a sad void:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ whereis export
&lt;&#x2F;span&gt;&lt;span&gt;export:
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Why do we have built-ins? Why isn’t everything a program?&lt;&#x2F;p&gt;
&lt;p&gt;In many cases, the reason is that the built-in does something that can’t be done by a program. For example, &lt;code&gt;export&lt;&#x2F;code&gt; modifies the environment of the shell and &lt;code&gt;cd&lt;&#x2F;code&gt; changes its current directory. This is something that can’t be done by a program, because a program can’t make these modifications to its parent process.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-2-1&quot;&gt;&lt;a href=&quot;#fn-2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In any case, if you want to know if a command is a built-in or not, you can use the &lt;code&gt;type&lt;&#x2F;code&gt; command:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ type export
&lt;&#x2F;span&gt;&lt;span&gt;export is a shell builtin
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Type is, of course, a builtin:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ type type
&lt;&#x2F;span&gt;&lt;span&gt;type is a shell builtin
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h1 id=&quot;examples&quot;&gt;Examples!&lt;&#x2F;h1&gt;
&lt;p&gt;Ok, now for the fun part. Let’s use what we learned to explore some interesting examples.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-1-the-separator&quot;&gt;Example 1: The &lt;code&gt;--&lt;&#x2F;code&gt; separator&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s start with an easy one. Sometimes you run a command that, in turn, runs another command. For example, let’s say you are working on a Rust command line program. You can run it during development with &lt;code&gt;cargo run&lt;&#x2F;code&gt; and pass arguments to it.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;cargo run someArg
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, your program will receive &lt;code&gt;someArg&lt;&#x2F;code&gt; as an argument.&lt;&#x2F;p&gt;
&lt;p&gt;Now imagine you added support for a new &lt;code&gt;--foo&lt;&#x2F;code&gt; flag and you want to try it out. If you do this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cargo run --foo someArg
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;you’ll get an error:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;error: Found argument &amp;#39;--foo&amp;#39; which wasn&amp;#39;t expected, or isn&amp;#39;t valid in this context
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;  If you tried to supply &amp;#39;--foo&amp;#39; as a value rather than a flag, use &amp;#39;-- --foo&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What’s happening here is that cargo thinks that &lt;code&gt;--foo&lt;&#x2F;code&gt; is a flag for &lt;code&gt;cargo run&lt;&#x2F;code&gt;, not for your program. A similar thing happens when you do &lt;code&gt;npm run some-script&lt;&#x2F;code&gt; and want to pass some arguments to the command executed by the script.&lt;&#x2F;p&gt;
&lt;p&gt;In both cases, the solution is to add a &lt;code&gt;--&lt;&#x2F;code&gt;. If we run &lt;code&gt;cargo run -- --foo&lt;&#x2F;code&gt;, then it will work fine. &lt;code&gt;--&lt;&#x2F;code&gt; here is a special argument that changes how Cargo (or npm) interprets the rest of its arguments.&lt;&#x2F;p&gt;
&lt;p&gt;What does the shell do with &lt;code&gt;--&lt;&#x2F;code&gt;? Hopefully the answer is obvious: nothing. This is not a metacharacter. Using &lt;code&gt;--&lt;&#x2F;code&gt; is just a convention used by many programs to change how they interpret their arguments; the shell doesn’t care about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-2-escaping-quotes&quot;&gt;Example 2: Escaping quotes&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to pass an argument that actually contains a quote, you can escape it with the other type of quote. That is:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo &amp;#39;The &amp;quot;quick&amp;quot; brown fox&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;The &amp;quot;quick&amp;quot; brown fox
&lt;&#x2F;span&gt;&lt;span&gt;$ echo &amp;quot;The &amp;#39;quick&amp;#39; brown fox&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;The &amp;#39;quick&amp;#39; brown fox
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want to include both kinds of quotes, you could do this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo &amp;quot;The &amp;#39;quick&amp;#39; brown \&amp;quot;fox\&amp;quot;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But, as mentioned before, it’s better to use single quotes by default. The problem is that you can’t escape single quotes with a backslash in bash and zsh (you can in fish, but let’s ignore that). So, if you want to pass a parameter that contains both double quotes and single quotes &lt;em&gt;and&lt;&#x2F;em&gt; you want to use single quotes for most of it, you have to do this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo &amp;#39;The &amp;#39;&amp;quot;&amp;#39;&amp;quot;&amp;#39;quick&amp;#39;&amp;quot;&amp;#39;&amp;quot;&amp;#39; brown &amp;quot;fox&amp;quot;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;The &amp;#39;quick&amp;#39; brown &amp;quot;fox&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The key to understand this monstrosity is that you can concatenate quotes strings. All of these are equivalent:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo foobarbaz
&lt;&#x2F;span&gt;&lt;span&gt;foobarbaz
&lt;&#x2F;span&gt;&lt;span&gt;$ echo &amp;quot;foo&amp;quot;&amp;quot;bar&amp;quot;&amp;quot;baz&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;foobarbaz
&lt;&#x2F;span&gt;&lt;span&gt;$ echo &amp;#39;foo&amp;#39;&amp;quot;bar&amp;quot;&amp;#39;baz&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;foobarbaz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If that makes sense, and if you squint hard enough, then you can understand the previous example. Here it is again, which each part in a different line:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ echo &amp;#39;The &amp;#39;\
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;quot;&amp;#39;&amp;quot;\
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;#39;quick&amp;#39;\
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;quot;&amp;#39;&amp;quot;\
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; &amp;#39; brown &amp;quot;fox&amp;quot;&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;The &amp;#39;quick&amp;#39; brown &amp;quot;fox&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For a good, alternative explanation of this, check &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;1250279&#x2F;3055448&quot;&gt;this answer&lt;&#x2F;a&gt; on StackOverflow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;example-3-conditions-in-bash-programming&quot;&gt;Example 3: Conditions in bash programming&lt;&#x2F;h2&gt;
&lt;p&gt;So far everything we’ve seen is related to running programs. But the language interpreted by shells like bash is pretty much a full programming language, including things like conditionals. For example, you can do:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;bash&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-bash &quot;&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt; 3 &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fd971f;&quot;&gt;-gt&lt;&#x2F;span&gt;&lt;span&gt; 1 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;3 is greater than 1&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#da4939;&quot;&gt;echo &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;Math is broken&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, you might think that the syntax for an &lt;code&gt;if&lt;&#x2F;code&gt; statement is something like this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;if [ &amp;lt;conditions&amp;gt; ]
&lt;&#x2F;span&gt;&lt;span&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;true&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;false&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where &lt;code&gt;&amp;lt;conditions&amp;gt;&lt;&#x2F;code&gt; uses a terrible syntax. But the actual syntax is this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;if &amp;lt;command&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;then
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;true&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;else
&lt;&#x2F;span&gt;&lt;span&gt;  &amp;lt;false&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;fi
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Where &lt;code&gt;&amp;lt;true&amp;gt;&lt;&#x2F;code&gt; will be executed if the command exits with a zero status code, and &lt;code&gt;&amp;lt;false&amp;gt;&lt;&#x2F;code&gt; will be executd if the command exits with a non-zero code.&lt;&#x2F;p&gt;
&lt;p&gt;Wait, does that mean that...?&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ whereis [
&lt;&#x2F;span&gt;&lt;span&gt;[: &#x2F;usr&#x2F;bin&#x2F;[ &#x2F;usr&#x2F;share&#x2F;man&#x2F;man1&#x2F;[.1.gz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Yes: &lt;code&gt;[&lt;&#x2F;code&gt; is a program.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-3-1&quot;&gt;&lt;a href=&quot;#fn-3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; It receives a list of arguments that are interpreted as conditions, and exits with a zero exit code if its arguments evaluate to true, and non-zero otherwise. Actually, &lt;code&gt;[&lt;&#x2F;code&gt; is kind of an alias to the &lt;code&gt;test&lt;&#x2F;code&gt; command.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ test 3 -gt 1
&lt;&#x2F;span&gt;&lt;span&gt;$ echo $?
&lt;&#x2F;span&gt;&lt;span&gt;0
&lt;&#x2F;span&gt;&lt;span&gt;$ test 3 -gt 3
&lt;&#x2F;span&gt;&lt;span&gt;$ echo $?
&lt;&#x2F;span&gt;&lt;span&gt;1
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Here we are using the &lt;code&gt;$?&lt;&#x2F;code&gt; variable, which contains the exit code of the last command, to check the result of the &lt;code&gt;test&lt;&#x2F;code&gt; command.)&lt;&#x2F;p&gt;
&lt;p&gt;And I said “kind of an alias” because &lt;code&gt;[&lt;&#x2F;code&gt; is not exactly the same as &lt;code&gt;test&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ [ 3 -gt 1
&lt;&#x2F;span&gt;&lt;span&gt;bash: [: missing `]&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can check by running &lt;code&gt;man test&lt;&#x2F;code&gt;, &lt;code&gt;[&lt;&#x2F;code&gt; is pretty much the same as &lt;code&gt;test&lt;&#x2F;code&gt;, except that it requires a &lt;code&gt;]&lt;&#x2F;code&gt; as its last argument.&lt;&#x2F;p&gt;
&lt;p&gt;Fun stuff.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;clarifications&quot;&gt;Clarifications&lt;&#x2F;h1&gt;
&lt;p&gt;There are a lot of simplifications in this article. Some of them are there to make the explanation easier to understand, and some of them are due to my own ignorance. This is a list of the ones I’m aware of and that I think are important:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Everything here is very UNIX specific. I think the core ideas apply to non-UNIX operating systems, but many of the details are probably different.&lt;&#x2F;li&gt;
&lt;li&gt;I didn’t mention system calls at all, even if they are relevant for a more common definition of a shell: “a shell is a program that provides an interface to the operating system”. This is probably a technically better definition, but I wanted to focus on the “interprets requests to run programs” part.&lt;&#x2F;li&gt;
&lt;li&gt;The environment is actually a list of strings, not a dictionary. These strings, by convention, look like &lt;code&gt;key=value&lt;&#x2F;code&gt; and are interpreted as a dictionary by programs and standard libraries.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;further-reading&quot;&gt;Further reading&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;The_Unix_Programming_Environment&quot;&gt;The UNIX Programming Environment&lt;&#x2F;a&gt; is a classic. It’s a bit dated, but it’s a great read anyway.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Advanced_Programming_in_the_Unix_Environment&quot;&gt;Advanced Programming in the UNIX Environment&lt;&#x2F;a&gt; is a more modern and technical book. I haven’t read it cover to cover, not even 10% of it, but it’s great as a reference.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;footnotes&quot;&gt;Footnotes&lt;&#x2F;h1&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;I’m going to use “program” for both “programs” and “processes”. There are a million explanations out there about the difference, so I won’t bother here. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-2&quot;&gt;
&lt;p&gt;There are also many built-in commands that have a program equivalent with the same name. For example, &lt;code&gt;echo&lt;&#x2F;code&gt; is a built-in command in bash, but there is also a &lt;code&gt;&#x2F;usr&#x2F;bin&#x2F;echo&lt;&#x2F;code&gt; program. I’m not completely sure why this is the case, but &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;76727697&#x2F;3055448&quot;&gt;one answer&lt;&#x2F;a&gt; seems to be “POSIX”, a topic I won’t delve into. &lt;a href=&quot;#fr-2-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-3&quot;&gt;
&lt;p&gt;I’m cheating a bit here. &lt;code&gt;[&lt;&#x2F;code&gt; is actually a shell built-in, but there’s also a program with the same name and functionality, similar to &lt;code&gt;echo&lt;&#x2F;code&gt;. Check the previous footnote for an explanation. &lt;a href=&quot;#fr-3-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hardhat: networks and providers</title>
        <published>2022-11-11T00:00:00+00:00</published>
        <updated>2022-11-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://fvictorio.github.io/posts/hardhat-networks-and-providers/"/>
        <id>https://fvictorio.github.io/posts/hardhat-networks-and-providers/</id>
        
        <content type="html" xml:base="https://fvictorio.github.io/posts/hardhat-networks-and-providers/">&lt;p&gt;&lt;em&gt;Originally published at &lt;a href=&quot;https:&#x2F;&#x2F;hackmd.io&#x2F;@fvictorio&#x2F;hardhat-networks-and-providers&quot;&gt;HackMD&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;An Ethereum node can be used to read the state of the blockchain or to send transactions that modify that state. To let you do this, Ethereum clients implement a protocol called &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;JSON-RPC&quot;&gt;JSON-RPC&lt;&#x2F;a&gt;. This allows applications to rely on a (somewhat) standardized set of methods that should work with any client.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sending-a-json-rpc-call&quot;&gt;Sending a JSON-RPC call&lt;&#x2F;h2&gt;
&lt;p&gt;We’ll use &lt;a href=&quot;https:&#x2F;&#x2F;www.alchemy.com&#x2F;&quot;&gt;Alchemy&lt;&#x2F;a&gt; in these examples and, if you want to reproduce them, you’ll need to get an API key from them. Even better, if you have a locally synced node, you can configure it to expose the JSON-RPC interface and use that instead.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s say we want to get the latest block number of the Goerli network. To do that, we have to use the &lt;code&gt;eth_blockNumber&lt;&#x2F;code&gt; JSON-RPC method, which returns the current block number. We can send this method via curl, or any other HTTP client:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ curl -X POST -H &amp;#39;Content-Type: application&#x2F;json&amp;#39; \
&lt;&#x2F;span&gt;&lt;span&gt;--data &amp;#39;{&amp;quot;jsonrpc&amp;quot;:&amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;method&amp;quot;:&amp;quot;eth_blockNumber&amp;quot;, &amp;quot;params&amp;quot;:[]}&amp;#39; \
&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;eth-goerli.alchemyapi.io&#x2F;v2&#x2F;&amp;lt;API_KEY&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;{&amp;quot;jsonrpc&amp;quot;: &amp;quot;2.0&amp;quot;, &amp;quot;id&amp;quot;: &amp;quot;1&amp;quot;, &amp;quot;result&amp;quot;: &amp;quot;0x8a73e2&amp;quot;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a mouthful, but there are only a few crucial parts; the rest is just boilerplate:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We are sending an HTTP POST request to the Alchemy endpoint.&lt;&#x2F;li&gt;
&lt;li&gt;The body of the request is a JSON object. This object includes the name of the method we are calling, &lt;code&gt;eth_blockNumber&lt;&#x2F;code&gt;. It also has a list of params, which is empty in this case.&lt;&#x2F;li&gt;
&lt;li&gt;We receive a JSON object as the response, which includes a &lt;code&gt;result&lt;&#x2F;code&gt; field with the value we are interested in: the current block number, as a hexadecimal string.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Other actions use other JSON-RPC methods. To send a signed transaction you use &lt;code&gt;eth_sendRawTransaction&lt;&#x2F;code&gt;, to get a transaction receipt you use &lt;code&gt;eth_getTransactionReceipt&lt;&#x2F;code&gt;, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;All of this is meant to illustrate what happens under the hood each time you interact with a node. But we don’t want to do something like that for everything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;json-rpc-networks-in-hardhat&quot;&gt;JSON-RPC networks in Hardhat&lt;&#x2F;h2&gt;
&lt;p&gt;You can interact with nodes via JSON-RPC more easily using &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;&quot;&gt;Hardhat&lt;&#x2F;a&gt;. We’ll see how to configure a network and then send calls to it.&lt;&#x2F;p&gt;
&lt;p&gt;Before starting, go to an empty directory and install Hardhat:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ cd &#x2F;path&#x2F;to&#x2F;some&#x2F;empty&#x2F;directory
&lt;&#x2F;span&gt;&lt;span&gt;$ npm install --save-dev hardhat
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now create a &lt;code&gt;hardhat.config.js&lt;&#x2F;code&gt; file with this content:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;exports &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  networks: {
&lt;&#x2F;span&gt;&lt;span&gt;    goerli: {
&lt;&#x2F;span&gt;&lt;span&gt;      url: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;eth-goerli.alchemyapi.io&#x2F;v2&#x2F;&amp;lt;API_KEY&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is adding a network to the Hardhat configuration. To configure a network you need at least two things: a name, which in this case is &lt;code&gt;goerli&lt;&#x2F;code&gt;, and a URL. We could’ve used a different name here, like &lt;code&gt;testnet&lt;&#x2F;code&gt;, if we wanted.&lt;&#x2F;p&gt;
&lt;p&gt;After setting this up, you can start a console connected to this network by running &lt;code&gt;npx hardhat console --network goerli&lt;&#x2F;code&gt;, or &lt;code&gt;hh console --network goerli&lt;&#x2F;code&gt; if you have installed the &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;guides&#x2F;shorthand.html&quot;&gt;Hardhat shorthand&lt;&#x2F;a&gt;. A node.js REPL will be started, where you can send JSON-RPC calls more easily:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; await network.provider.send(&amp;quot;eth_blockNumber&amp;quot;, [])
&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;0x8a733e&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, &lt;code&gt;network.provider&lt;&#x2F;code&gt; is an object that implements the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ethereum&#x2F;EIPs&#x2F;blob&#x2F;master&#x2F;EIPS&#x2F;eip-1193.md&quot;&gt;EIP-1193&lt;&#x2F;a&gt; standard. This is an abstraction with a minimal API used to interact with a node via JSON-RPC. When you use &lt;code&gt;window.ethereum&lt;&#x2F;code&gt; in a dapp, you are using an instance of a EIP-1193 provider exposed by the browser wallet.&lt;&#x2F;p&gt;
&lt;p&gt;The only part we care about here is that this object has a &lt;code&gt;send&lt;&#x2F;code&gt; function that receives the name of the method and a list of arguments.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Aside: the correct way to make calls in EIP-1193 is with the &lt;code&gt;request&lt;&#x2F;code&gt; method, but here we’ll use the old &lt;code&gt;send&lt;&#x2F;code&gt; method because it’s more concise.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can have more than one network in your configuration:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;js&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-js &quot;&gt;&lt;code class=&quot;language-js&quot; data-lang=&quot;js&quot;&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;exports &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  networks: {
&lt;&#x2F;span&gt;&lt;span&gt;    mainnet: {
&lt;&#x2F;span&gt;&lt;span&gt;      url: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;eth-mainnet.alchemyapi.io&#x2F;v2&#x2F;&amp;lt;API_KEY&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    },
&lt;&#x2F;span&gt;&lt;span&gt;    goerli: {
&lt;&#x2F;span&gt;&lt;span&gt;      url: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;https:&#x2F;&#x2F;eth-goerli.alchemyapi.io&#x2F;v2&#x2F;&amp;lt;API_KEY&amp;gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But you can only connect to one of them at a time. If we exit the console and run &lt;code&gt;hh console --network mainnet&lt;&#x2F;code&gt;, we can make the same call as before but to the mainnet network instead:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; await network.provider.send(&amp;quot;eth_blockNumber&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;0xc607e5&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;local-development-node&quot;&gt;Local development node&lt;&#x2F;h2&gt;
&lt;p&gt;Using a testnet for local development is slow, and you need to get test ether from a faucet. An easier and faster alternative is to use the local development node that comes with Hardhat. This node starts an instance of the Hardhat Network, which includes features like &lt;code&gt;console.log&lt;&#x2F;code&gt; and Solidity stack traces.&lt;&#x2F;p&gt;
&lt;p&gt;If you run &lt;code&gt;hh node&lt;&#x2F;code&gt; in a terminal, an HTTP server with this development node will start listening for requests in &lt;code&gt;http:&#x2F;&#x2F;localhost:8545&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;$ hh node
&lt;&#x2F;span&gt;&lt;span&gt;Started HTTP and WebSocket JSON-RPC server at http:&#x2F;&#x2F;127.0.0.1:8545&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Accounts
&lt;&#x2F;span&gt;&lt;span&gt;========
&lt;&#x2F;span&gt;&lt;span&gt;Account #0: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (10000 ETH)
&lt;&#x2F;span&gt;&lt;span&gt;Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can now connect to this network from another terminal running &lt;code&gt;hh console --network localhost&lt;&#x2F;code&gt; and make the same call as before:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; await network.provider.send(&amp;quot;eth_blockNumber&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;&amp;#39;0x0&amp;#39;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The response is &lt;code&gt;0x0&lt;&#x2F;code&gt; here because this is a new network that hasn’t received any transactions.&lt;&#x2F;p&gt;
&lt;p&gt;But wait, what is this &lt;code&gt;localhost&lt;&#x2F;code&gt; network? We haven’t added it to our config. The reason we can use it is that Hardhat comes with this pre-defined network, and it’s pretty much equivalent to adding this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;localhost: {
&lt;&#x2F;span&gt;&lt;span&gt;  url: &amp;quot;http:&#x2F;&#x2F;localhost:8545&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Since connecting to this particular address and port is so common, Hardhat includes it by default. But you can explicitly add it to your config to customize it.&lt;&#x2F;p&gt;
&lt;p&gt;So now we have an easy way to develop locally. For example, if we want to run our tests, we can start a node in one terminal and then run &lt;code&gt;hh test --network localhost&lt;&#x2F;code&gt; in another. But this is very cumbersome. It means working with two different terminals and killing and starting the node again and again every time we want to start from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, you don’t need to do that. Besides &lt;code&gt;localhost&lt;&#x2F;code&gt;, Hardhat comes with another pre-defined network: &lt;code&gt;hardhat&lt;&#x2F;code&gt;. This is the same network used by the development node, but instead of starting an HTTP server, it’s an in-process network that is created when you run your task, and killed at the end of it. So if you run &lt;code&gt;hh test --network hardhat&lt;&#x2F;code&gt;, the result will be pretty much equivalent to the combination of starting a new node, running &lt;code&gt;hh test --network localhost&lt;&#x2F;code&gt;, and then killing the node, all in one command.&lt;&#x2F;p&gt;
&lt;p&gt;Besides, this is the default network, so you only need to do &lt;code&gt;hh test&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hardhat-network&quot;&gt;Hardhat Network&lt;&#x2F;h2&gt;
&lt;p&gt;This &lt;code&gt;hardhat&lt;&#x2F;code&gt; network is different from the other networks we have configured so far, because no HTTP server is started at all. Instead, the provider that will be exposed is connected to an in-process, ephemeral instance of the Hardhat Network. This might surprise you if you thought that you could only interact with JSON-RPC via HTTP, but the protocol is actually transport-agnostic.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;hardhat-network&#x2F;reference&#x2F;#config&quot;&gt;configuration options for the Hardhat Network&lt;&#x2F;a&gt; are also different from the options for the &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;config&#x2F;#json-rpc-based-networks&quot;&gt;external networks&lt;&#x2F;a&gt;. For example, external networks have a &lt;code&gt;url&lt;&#x2F;code&gt; configuration field, but the Hardhat network configuration doesn’t. On the other hand, the Hardhat network has a &lt;code&gt;blockGasLimit&lt;&#x2F;code&gt; option that doesn’t exist for other networks.&lt;&#x2F;p&gt;
&lt;p&gt;Keep in mind that the &lt;code&gt;hardhat&lt;&#x2F;code&gt; entry of your configuration is used to configure both the in-process network used by default, and the network started when you run &lt;code&gt;hh node&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ethers-js&quot;&gt;Ethers.js&lt;&#x2F;h2&gt;
&lt;p&gt;Technically, you can do anything you want just with a JSON-RPC provider, but this is still a very low-level interface. Libraries like &lt;a href=&quot;https:&#x2F;&#x2F;docs.ethers.io&#x2F;v5&#x2F;&quot;&gt;ethers.js&lt;&#x2F;a&gt; offer a higher-level functionality to make your life easier.&lt;&#x2F;p&gt;
&lt;p&gt;One of these interfaces is a set of &lt;a href=&quot;https:&#x2F;&#x2F;docs.ethers.io&#x2F;v5&#x2F;single-page&#x2F;#&#x2F;v5&#x2F;api&#x2F;providers&#x2F;&quot;&gt;providers&lt;&#x2F;a&gt;. These are like the EIP-1193 provider we’ve been used so far, but with many helper methods. For example, we previously called the &lt;code&gt;eth_blockNumber&lt;&#x2F;code&gt; method and got a hexadecimal string in response. With an ethers provider, you would do this instead:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; await anEthersProvider.getBlockNumber()
&lt;&#x2F;span&gt;&lt;span&gt;9073582
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are two significant differences here: we use a specific and more readable method to get the current block number, and we get a number in response, not a hexadecimal string.&lt;&#x2F;p&gt;
&lt;p&gt;How do we convert our provider into an ethers.js provider? The easiest way is to use ethers.js’s &lt;a href=&quot;https:&#x2F;&#x2F;docs.ethers.io&#x2F;v5&#x2F;single-page&#x2F;#&#x2F;v5&#x2F;api&#x2F;providers&#x2F;other&#x2F;-%23-Web3Provider&quot;&gt;&lt;code&gt;Web3Provider&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to wrap our existing provider. If you have ethers.js installed, you can start an &lt;code&gt;hh console&lt;&#x2F;code&gt; and execute this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; const ethers = require(&amp;quot;ethers&amp;quot;)
&lt;&#x2F;span&gt;&lt;span&gt;undefined
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; const anEthersProvider = new ethers.providers.Web3Provider(network.provider)
&lt;&#x2F;span&gt;&lt;span&gt;undefined
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; await anEthersProvider.getBlockNumber()
&lt;&#x2F;span&gt;&lt;span&gt;9073591
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even easier, you can use the &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;plugins&#x2F;nomiclabs-hardhat-ethers.html&quot;&gt;&lt;code&gt;@nomiclabs&#x2F;hardhat-ethers&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; plugin. This plugin will add an ethers property to the Hardhat runtime environment, which has all the functionality from the ethers package, but that also includes some extra things, like an already initialized provider. So if you install the plugin, import it in your config, and then start a Hardhat console again, you’ll be able to do this:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#383838;color:#e6e1dc;&quot;&gt;&lt;code&gt;&lt;span&gt;&amp;gt; await ethers.provider.getBlockNumber()
&lt;&#x2F;span&gt;&lt;span&gt;9073599
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;learn-more&quot;&gt;Learn more&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;If you want to know more about the JSON-RPC interface of Ethereum nodes, you can check &lt;a href=&quot;https:&#x2F;&#x2F;ethereum.org&#x2F;en&#x2F;developers&#x2F;docs&#x2F;apis&#x2F;json-rpc&#x2F;&quot;&gt;the ethereum.org page&lt;&#x2F;a&gt;. There is work in progress to have an up to date specification in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ethereum&#x2F;eth1.0-apis&quot;&gt;eth1.0-apis&lt;&#x2F;a&gt; repository, which is used to generate &lt;a href=&quot;https:&#x2F;&#x2F;playground.open-rpc.org&#x2F;?schemaUrl=https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;ethereum&#x2F;eth1.0-apis&#x2F;assembled-spec&#x2F;openrpc.json&amp;amp;uiSchema%5BappBar%5D%5Bui:splitView%5D=false&amp;amp;uiSchema%5BappBar%5D%5Bui:input%5D=false&amp;amp;uiSchema%5BappBar%5D%5Bui:examplesDropdown%5D=false&quot;&gt;this site&lt;&#x2F;a&gt;. Finally, this information used to live in the &lt;a href=&quot;https:&#x2F;&#x2F;eth.wiki&#x2F;json-rpc&#x2F;API&quot;&gt;Ethereum Wiki&lt;&#x2F;a&gt; and, while this page isn’t maintained anymore, it still has useful information.&lt;&#x2F;li&gt;
&lt;li&gt;To learn more about the Hardhat Network, check &lt;a href=&quot;https:&#x2F;&#x2F;hardhat.org&#x2F;hardhat-network&#x2F;&quot;&gt;its docs&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Understanding gas costs after Berlin</title>
        <published>2021-04-11T00:00:00+00:00</published>
        <updated>2021-04-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://fvictorio.github.io/posts/understanding-gas-costs-after-berlin/"/>
        <id>https://fvictorio.github.io/posts/understanding-gas-costs-after-berlin/</id>
        
        <content type="html" xml:base="https://fvictorio.github.io/posts/understanding-gas-costs-after-berlin/">&lt;p&gt;&lt;em&gt;Originally published at &lt;a href=&quot;https:&#x2F;&#x2F;hackmd.io&#x2F;@fvictorio&#x2F;gas-costs-after-berlin&quot;&gt;HackMD&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The Berlin hard fork will &lt;a href=&quot;https:&#x2F;&#x2F;blog.ethereum.org&#x2F;2021&#x2F;03&#x2F;08&#x2F;ethereum-berlin-upgrade-announcement&#x2F;&quot;&gt;go live on mainnet on April 14&lt;&#x2F;a&gt;, introducing four new EIPs. Two of them (&lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2929&quot;&gt;EIP-2929&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2930&quot;&gt;EIP-2930&lt;&#x2F;a&gt;) affect how the gas cost of a transaction is computed. This article explains how (some) gas costs were calculated before Berlin, how this will change with EIP-2929, and how to use the Access Lists feature introduced by EIP-2930.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;tl;dr&lt;&#x2F;h2&gt;
&lt;p&gt;This is a long article, so you can just read this and close the tab:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Berlin hard fork changes the gas cost of some opcodes. If you have a hardcoded gas value in a dapp or a smart contract, they might stop working. And if this happens and the smart contract is non-upgradeable, consumers will need to employ access lists (EIP-2930) to use it.&lt;&#x2F;li&gt;
&lt;li&gt;Access lists can be used to reduce gas costs a little, but they could actually increase the total gas consumed in some scenarios.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;geth&lt;&#x2F;code&gt; includes a new RPC method called &lt;code&gt;eth_createAccessList&lt;&#x2F;code&gt; to simplify the creation of access lists.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;gas-costs-before-berlin&quot;&gt;Gas costs before Berlin&lt;&#x2F;h2&gt;
&lt;p&gt;Each opcode executed by the EVM has an associated gas cost. For most of them, this cost is fixed: &lt;code&gt;PUSH1&lt;&#x2F;code&gt; always consumes 3 units of gas, &lt;code&gt;MUL&lt;&#x2F;code&gt; consumes 5, and so on. For others it is variable: the &lt;code&gt;SHA3&lt;&#x2F;code&gt; opcode’s cost depends on the size of its input, for example.&lt;&#x2F;p&gt;
&lt;p&gt;We’ll focus on the &lt;code&gt;SLOAD&lt;&#x2F;code&gt; and &lt;code&gt;SSTORE&lt;&#x2F;code&gt; opcodes since they are the ones most affected by the Berlin hard fork. We’ll talk later about those that target an address, like all the &lt;code&gt;EXT*&lt;&#x2F;code&gt; and &lt;code&gt;CALL*&lt;&#x2F;code&gt; opcodes, since their gas cost changes too.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sload-before-berlin&quot;&gt;&lt;code&gt;SLOAD&lt;&#x2F;code&gt; before Berlin&lt;&#x2F;h3&gt;
&lt;p&gt;Without EIP-2929, the cost of &lt;code&gt;SLOAD&lt;&#x2F;code&gt; is simple: it always costs 800 of gas. So there isn’t much to say about it (for now).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sstore-before-berlin&quot;&gt;&lt;code&gt;SSTORE&lt;&#x2F;code&gt; before Berlin&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;code&gt;SSTORE&lt;&#x2F;code&gt; is maybe the most complex opcode in terms of gas because its cost depends on things like the current value of the storage slot, the new value, and whether it was previously modified. We’ll analyze only some scenarios to get a basic understanding; if you want to learn more, read the EIPs linked at the end of this article.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the value of the slot changes from 0 to 1 (or any non-zero value), the cost is 20000&lt;&#x2F;li&gt;
&lt;li&gt;If the value of the slot changes from 1 to 2 (or any other non-zero value), the cost is 5000.&lt;&#x2F;li&gt;
&lt;li&gt;If the value of the slot changes from 1 (or any non-zero value) to 0, the cost is &lt;em&gt;also&lt;&#x2F;em&gt; 5000, but you get a gas refund at the end of the transaction. We won’t cover refunds in this article since they are not affected by Berlin.&lt;&#x2F;li&gt;
&lt;li&gt;If the value was previously modified during the same transaction, all the subsequent &lt;code&gt;SSTORE&lt;&#x2F;code&gt;s cost 800.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The details are not that interesting here. The important part is that &lt;code&gt;SSTORE&lt;&#x2F;code&gt; is &lt;em&gt;expensive&lt;&#x2F;em&gt; and that its cost depends on several factors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gas-costs-after-eip-2929&quot;&gt;Gas costs after EIP-2929&lt;&#x2F;h2&gt;
&lt;p&gt;EIP-2929 changes all these values. But before getting into that, we need to talk about an important concept introduced by the EIP: &lt;strong&gt;accessed addresses and accessed storage keys&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;An address or a storage key is considered accessed if it was previously “used” during the transaction. For example, when you &lt;code&gt;CALL&lt;&#x2F;code&gt; another contract, the address of that contract is marked as accessed. Similarly, when you &lt;code&gt;SLOAD&lt;&#x2F;code&gt; or &lt;code&gt;SSTORE&lt;&#x2F;code&gt; some slot, it will be considered accessed for the rest of the transaction. It doesn’t matter which opcode did it: if an &lt;code&gt;SLOAD&lt;&#x2F;code&gt; reads a slot, it will be considered accessed for both the next &lt;code&gt;SLOAD&lt;&#x2F;code&gt;s and the next &lt;code&gt;SSTORE&lt;&#x2F;code&gt;s.&lt;&#x2F;p&gt;
&lt;p&gt;Something important to notice here is that storage keys are “inside” some address. As the EIP explains it:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;When executing a transaction, maintain a set &lt;code&gt;accessed_addresses: Set[Address]&lt;&#x2F;code&gt; and &lt;code&gt;accessed_storage_keys: Set[Tuple[Address, Bytes32]]&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That is, when we say that a storage slot is accessed, we are actually saying that a pair &lt;code&gt;(address, storageKey)&lt;&#x2F;code&gt; was accessed.&lt;&#x2F;p&gt;
&lt;p&gt;With that being said, let’s talk about the new gas costs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sload-after-berlin&quot;&gt;&lt;code&gt;SLOAD&lt;&#x2F;code&gt; after Berlin&lt;&#x2F;h3&gt;
&lt;p&gt;Before Berlin, &lt;code&gt;SLOAD&lt;&#x2F;code&gt; had a fixed cost of 800. Now, it depends on whether that storage slot was already accessed or not. If it wasn’t accessed, the cost is 2100; if it was, it is 100. So, an &lt;code&gt;SLOAD&lt;&#x2F;code&gt; costs 2000 less if the slot is in the list of accessed storage keys.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sstore-after-berlin&quot;&gt;&lt;code&gt;SSTORE&lt;&#x2F;code&gt; after Berlin&lt;&#x2F;h3&gt;
&lt;p&gt;Let’s revisit our previous &lt;code&gt;SSTORE&lt;&#x2F;code&gt; examples in the context of EIP-2929:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If the value of the slot changes from 0 to 1 (or any non-zero value), the cost is:
&lt;ul&gt;
&lt;li&gt;22100 if the storage key wasn’t accessed&lt;&#x2F;li&gt;
&lt;li&gt;20000 if it was&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;If the value of the slot changes from 1 to 2 (or any other non-zero value), the cost is:
&lt;ul&gt;
&lt;li&gt;5000 if the storage key wasn’t accessed&lt;&#x2F;li&gt;
&lt;li&gt;2900 if it was&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;If the value of the slot changes from 1 (or any non-zero value) to 0, the cost is the same as the previous item, plus the refund.&lt;&#x2F;li&gt;
&lt;li&gt;If the value was previously modified during the same transaction, all the subsequent &lt;code&gt;SSTORE&lt;&#x2F;code&gt;s cost 100.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As you can see, the first &lt;code&gt;SSTORE&lt;&#x2F;code&gt; costs 2100 less if the slot it’s modifying was previously accessed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;putting-it-all-together&quot;&gt;Putting it all together&lt;&#x2F;h2&gt;
&lt;p&gt;That was a mouthful, so here’s a table comparing all the values mentioned so far:&lt;&#x2F;p&gt;
&lt;div&gt;
  &lt;table&gt;
    &lt;thead style=&quot;text-align: center; font-weight: bold&quot;&gt;
      &lt;tr&gt;
        &lt;td rowspan=&quot;2&quot;&gt;OPCODE&lt;&#x2F;td&gt;
        &lt;td rowspan=&quot;2&quot;&gt;Before Berlin&lt;&#x2F;td&gt;
        &lt;td colspan=&quot;2&quot;&gt;After Berlin&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td&gt;Not accessed&lt;&#x2F;td&gt;
        &lt;td&gt;Accessed&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
    &lt;&#x2F;thead&gt;
    &lt;tbody style=&quot;text-align: center&quot;&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left; font-family: monospace&quot;&gt;SLOAD&lt;&#x2F;td&gt;
        &lt;td&gt;800&lt;&#x2F;td&gt;
        &lt;td&gt;2100&lt;&#x2F;td&gt;
        &lt;td&gt;100&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;font-family: monospace&quot;&gt;SSTORE&lt;&#x2F;span&gt; from 0 to 1&lt;&#x2F;td&gt;
        &lt;td&gt;20000&lt;&#x2F;td&gt;
        &lt;td&gt;22100&lt;&#x2F;td&gt;
        &lt;td&gt;20000&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;font-family: monospace&quot;&gt;SSTORE&lt;&#x2F;span&gt; from 1 to 2&lt;&#x2F;td&gt;
        &lt;td&gt;5000&lt;&#x2F;td&gt;
        &lt;td&gt;5000&lt;&#x2F;td&gt;
        &lt;td&gt;2900&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;font-family: monospace&quot;&gt;SLOAD + SSTORE*&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;
        &lt;td&gt;5800&lt;&#x2F;td&gt;
        &lt;td&gt;5000&lt;&#x2F;td&gt;
        &lt;td&gt;3000&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;font-family: monospace&quot;&gt;SSTORE* + SLOAD&lt;&#x2F;span&gt;&lt;&#x2F;td&gt;
        &lt;td&gt;5800&lt;&#x2F;td&gt;
        &lt;td&gt;5100&lt;&#x2F;td&gt;
        &lt;td&gt;3000&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;span style=&quot;font-family: monospace&quot;&gt;SSTORE&lt;&#x2F;span&gt; of an already written slot&lt;&#x2F;td&gt;
        &lt;td&gt;800&lt;&#x2F;td&gt;
        &lt;td colspan=&quot;2&quot;&gt;100&lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
      &lt;tr&gt;
        &lt;td colspan=&quot;4&quot; style=&quot;font-size: small; margin-top: 5px; text-align: left;&quot;&gt;
          &lt;span&gt;
            *From a non-zero value to a different non-zero value, like in the third row
          &lt;&#x2F;span&gt;
        &lt;&#x2F;td&gt;
      &lt;&#x2F;tr&gt;
    &lt;&#x2F;tbody&gt;
  &lt;&#x2F;table&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Notice that in the last row it doesn’t make sense to talk about the slot having been accessed or not because, if it was previously written, then it was also accessed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;eip-2930-optional-access-list-transactions&quot;&gt;EIP-2930: Optional Access List transactions&lt;&#x2F;h2&gt;
&lt;p&gt;The other EIP we mentioned at the beginning was EIP-2930. This EIP adds a new type of transaction that can include an access list in the transaction payload. This means that you can declare beforehand which addresses and slots should be considered as accessed before the transaction’s execution starts. For example, an &lt;code&gt;SLOAD&lt;&#x2F;code&gt; of a non-accessed slot costs 2100, but if that slot was included in the transaction’s access list, then that same opcode will cost 100.&lt;&#x2F;p&gt;
&lt;p&gt;But if the gas costs are lower when an address or storage key is already accessed, does this mean that we can add everything to the transaction’s access list and get a gas reduction? Yay, free gas! Well, not exactly, because you also need to pay gas for each address and each storage key that you add.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s see an example. Say we are sending a transaction to contract &lt;code&gt;A&lt;&#x2F;code&gt;. An access list could look like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span&gt;accessList: [{
&lt;&#x2F;span&gt;&lt;span&gt;  address: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&amp;lt;address of A&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  storageKeys: [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0x0000000000000000000000000000000000000000000000000000000000000000&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we send a transaction with this access list, and the first opcode that uses the &lt;code&gt;0x0&lt;&#x2F;code&gt; slot is a &lt;code&gt;SLOAD&lt;&#x2F;code&gt;, it will cost 100 instead of 2100. That’s a gas reduction of 2000. But each storage key included in the transaction’s access list has a cost of 1900. So we only save 100 of gas. (If the first opcode to access that slot is an &lt;code&gt;SSTORE&lt;&#x2F;code&gt; instead, we would save 2100 of gas, which means that we’d save 200 of gas in total if we consider the cost of the storage key.)&lt;&#x2F;p&gt;
&lt;p&gt;Does this mean that we always save gas when using transaction’s with access lists? Well, no, because we also pay gas for the address in the access list (&lt;code&gt;&quot;&amp;lt;address of A&amp;gt;&quot;&lt;&#x2F;code&gt; in our example).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;accessed-addresses&quot;&gt;Accessed addresses&lt;&#x2F;h2&gt;
&lt;p&gt;So far, we’ve been talking only about the &lt;code&gt;SLOAD&lt;&#x2F;code&gt; and &lt;code&gt;SSTORE&lt;&#x2F;code&gt; opcodes, but those aren’t the only ones that change after Berlin. For example, the &lt;code&gt;CALL&lt;&#x2F;code&gt; opcode had a fixed cost of 700. But after EIP-2929 its cost is 2600 if the address is not in the access list and 100 if it is. And, like the accessed storage keys, it doesn’t matter what OPCODE accessed that address before (for example, if an &lt;code&gt;EXTCODESIZE&lt;&#x2F;code&gt; was called first, then that opcode will cost 2600, and any subsequent &lt;code&gt;EXTCODESIZE&lt;&#x2F;code&gt;, &lt;code&gt;CALL&lt;&#x2F;code&gt;, &lt;code&gt;STATICCALL&lt;&#x2F;code&gt; &lt;strong&gt;that uses the same address&lt;&#x2F;strong&gt; will cost 100).&lt;&#x2F;p&gt;
&lt;p&gt;How is this affected by transactions with access lists? For example, if we send a transaction to contract &lt;code&gt;A&lt;&#x2F;code&gt;, and that contract calls another contract &lt;code&gt;B&lt;&#x2F;code&gt;, then we can include an access list like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span&gt;accessList: [{ address: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&amp;lt;address of B&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, storageKeys: [] }]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We’ll have to pay a cost of 2400 to include this access list in the transaction, but then the first opcode that uses the address of &lt;code&gt;B&lt;&#x2F;code&gt; will cost 100 instead of 2600. So we saved 100 of gas by doing this. And if &lt;code&gt;B&lt;&#x2F;code&gt; uses its storage somehow and we know which keys it will use, then we can also include them in the access list and save 100&#x2F;200 of gas for each one (depending on whether the first opcode is an &lt;code&gt;SLOAD&lt;&#x2F;code&gt; or an &lt;code&gt;SSTORE&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;But why are we talking about another contract? What happens with the contract that we are calling? Why don’t we do this?&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span&gt;accessList: [
&lt;&#x2F;span&gt;&lt;span&gt;  {address: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&amp;lt;address of A&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, storageKeys: []},
&lt;&#x2F;span&gt;&lt;span&gt;  {address: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&amp;lt;address of B&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, storageKeys: []},
&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We could do it, but it wouldn’t be worth it because EIP-2929 specifies that the address of the contract that is being called (that is, &lt;code&gt;tx.to&lt;&#x2F;code&gt;) is always included in the &lt;code&gt;accessed_addresses&lt;&#x2F;code&gt; list. So we are paying 2400 more for nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s analyze our example of the previous section again:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span&gt;accessList: [{
&lt;&#x2F;span&gt;&lt;span&gt;  address: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;&amp;lt;address of A&amp;gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;  storageKeys: [
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0x0000000000000000000000000000000000000000000000000000000000000000&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;  ]
&lt;&#x2F;span&gt;&lt;span&gt;}]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will actually be wasteful unless we include several storage keys more. If we assume that a storage key is always used first by an &lt;code&gt;SLOAD&lt;&#x2F;code&gt;, then we need at least 24 storage keys just to break even.&lt;&#x2F;p&gt;
&lt;p&gt;As you can imagine, analyzing this and creating an access list by hand is not fun. Luckily, there is a better way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-eth-createaccesslist-rpc-method&quot;&gt;The &lt;code&gt;eth_createAccessList&lt;&#x2F;code&gt; RPC method&lt;&#x2F;h2&gt;
&lt;p&gt;Geth (starting from version 1.10.2) includes a new &lt;code&gt;eth_createAccessList&lt;&#x2F;code&gt; RPC method that you can use to generate access lists. It is used like &lt;code&gt;eth_estimateGas&lt;&#x2F;code&gt;, but instead of a gas estimation, it returns something like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;json&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-json &quot;&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;accessList&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;    {
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;address&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0xb0ee076d7779a6ce152283f009f4c32b5f88756c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;storageKeys&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0x0000000000000000000000000000000000000000000000000000000000000000&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0x0000000000000000000000000000000000000000000000000000000000000001&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;      ]
&lt;&#x2F;span&gt;&lt;span&gt;    }
&lt;&#x2F;span&gt;&lt;span&gt;  ],
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;gasUsed&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c1be91;&quot;&gt;&amp;quot;0x8496&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is, it gives you the list of addresses and storage keys that will be used by that transaction, plus the gas consumed &lt;em&gt;if the access list is included&lt;&#x2F;em&gt;. (And, like &lt;code&gt;eth_estimateGas&lt;&#x2F;code&gt;, this is an estimation; the list could change when the transaction is actually mined.) But, again, this doesn’t mean that this gas will be lower than the gas used if you just send the same transaction without an access list!&lt;&#x2F;p&gt;
&lt;p&gt;I suppose we’ll discover over time what’s the proper way of doing this, but my pseudo-code guess is this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;javascript&quot; style=&quot;background-color:#383838;color:#e6e1dc;&quot; class=&quot;language-javascript &quot;&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;gasEstimation &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;estimateGas&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#6e9cbe;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span&gt;{ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;accessList&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;gasUsed &lt;&#x2F;span&gt;&lt;span&gt;} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;createAccessList&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;gasUsed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;gasEstimation&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;delete &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;accessList&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;to&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;accessList &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cc7833;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;accessList&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffc66d;&quot;&gt;sendTransaction&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#d0d0ff;&quot;&gt;tx&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;unbricking-contracts&quot;&gt;Unbricking contracts&lt;&#x2F;h2&gt;
&lt;p&gt;It is important to mention that the main purpose of Access Lists is not to use gas. As the EIP &lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2930#motivation&quot;&gt;explains it&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Mitigates contract breakage risks introduced by EIP-2929, as transactions could pre-specify and pre-pay for the accounts and storage slots that the transaction plans to access; as a result, in the actual execution, the SLOAD and EXT* opcodes would only cost 100 gas: low enough that it would not only prevent breakage due to that EIP but also “unstuck” any contracts that became stuck due to EIP 1884.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This means that if a contract makes assumptions about the cost of executing something, the increase in gas costs could break it. For example, a contract makes a call to another contract like &lt;code&gt;someOtherContract.someFunction{gas: 34500}()&lt;&#x2F;code&gt; because it assumes that &lt;code&gt;someFunction&lt;&#x2F;code&gt; will use exactly 34500 of gas, then it will break. But if you include the proper access list in the transaction, then the contract will work again.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;check-it-yourself&quot;&gt;Check it yourself&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to test this yourself, clone &lt;a href=&quot;http:&#x2F;&#x2F;github.com&#x2F;fvictorio&#x2F;berlin-gas-costs&quot;&gt;this repo&lt;&#x2F;a&gt; which has several examples that can be executed using &lt;a href=&quot;https:&#x2F;&#x2F;fvictorio.github.io&#x2F;posts&#x2F;understanding-gas-costs-after-berlin&#x2F;hardhat.org&quot;&gt;Hardhat&lt;&#x2F;a&gt; and geth. Check the README for the instructions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;was-this-fun&quot;&gt;Was this fun?&lt;&#x2F;h2&gt;
&lt;p&gt;If this low-level mumbo-jumbo is your idea of fun, you should know that &lt;a href=&quot;https:&#x2F;&#x2F;nomiclabs.io&#x2F;&quot;&gt;Nomic Labs&lt;&#x2F;a&gt; is &lt;a href=&quot;https:&#x2F;&#x2F;www.notion.so&#x2F;Nomic-Labs-jobs-991b37c547554f75b89a95f437fd5056&quot;&gt;hiring&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2929&quot;&gt;EIP-2929&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2930&quot;&gt;EIP-2930&lt;&#x2F;a&gt; are the two Berlin EIPs relevant to this article.&lt;&#x2F;li&gt;
&lt;li&gt;EIP-2930 depends on another part of Berlin: &lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2718&quot;&gt;EIP-2718&lt;&#x2F;a&gt;, also called Typed Transactions.&lt;&#x2F;li&gt;
&lt;li&gt;EIP-2929 refers to &lt;a href=&quot;https:&#x2F;&#x2F;eips.ethereum.org&#x2F;EIPS&#x2F;eip-2200&quot;&gt;EIP-2200&lt;&#x2F;a&gt; a lot, so if you want to understand gas costs more in depth, you should start there.&lt;&#x2F;li&gt;
&lt;li&gt;For more complex examples comparing how gas usage changes, check &lt;a href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;holiman&#x2F;aa7d2d28a9747548a0a14321a1572b22&quot;&gt;this&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
</feed>
