{"@attributes":{"version":"2.0"},"channel":{"title":"DEV Community: Rafael Abuawad","description":"The latest articles on DEV Community by Rafael Abuawad (@rabuawad).","link":"https:\/\/dev.to\/rabuawad","image":{"url":"https:\/\/media2.dev.to\/dynamic\/image\/width=90,height=90,fit=cover,gravity=auto,format=auto\/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F232437%2F0a8251cd-1b32-4675-8f6e-dc4fc2a23885.png","title":"DEV Community: Rafael Abuawad","link":"https:\/\/dev.to\/rabuawad"},"language":"en","item":[{"title":"Create your own Uniswap DeFi Application\ud83e\udd84! From scratch using Vyper & Python\ud83d\udc0d","pubDate":"Fri, 08 Dec 2023 15:45:42 +0000","link":"https:\/\/dev.to\/rabuawad\/create-your-own-uniswap-defi-application-from-scratch-using-vyper-python-3i9h","guid":"https:\/\/dev.to\/rabuawad\/create-your-own-uniswap-defi-application-from-scratch-using-vyper-python-3i9h","description":"<h2>\n  \n  \n  Introduction\n<\/h2>\n\n<p>DeFi, short for Decentralized Finance, is a prominent use case for blockchain technology. Among the many protocols that exist, Uniswap was one of the earliest to implement the automatic market maker (AMM) model and remains one of the most widely used solutions to date.<\/p>\n\n<p>To develop our solution, we have chosen to use Vyper. This is because it offers clear readability, built-in security features, and optimization capabilities right out of the box. By leveraging Vyper, we aim to enhance the overall quality and reliability of our code.<\/p>\n\n<h3>\n  \n  \n  What is an AMM?\n<\/h3>\n\n<p>Automated market makers (AMMs) are part of the decentralized finance (Defi) ecosystem. They allow digital assets to be traded in a permissionless and automatic way by using liquidity pools rather than a traditional market of buyers and sellers. AMM users supply liquidity pools with crypto tokens, whose prices are determined by a constant mathematical formula. Liquidity pools can be optimized for different purposes, and are proving to be an important instrument in the Defi ecosystem. <a href=\"https:\/\/chain.link\/education-hub\/what-is-an-automated-market-maker-amm\">In this tutorial, we are going to use a constant-product AMM.<\/a><\/p>\n\n<h2>\n  \n  \n  Setup project\n<\/h2>\n\n<p>For this particular project, we have decided to use ApeWorx, a novel framework for smart contract development that utilizes Python. We chose ApeWorx for its simplicity, ease of use, and powerful capabilities. Additionally, the framework supports plugins, allowing us to extend its functionality and enhance our development process even further.<\/p>\n\n<p>By leveraging ApeWorx, we aim to streamline our smart contract development workflow, improve the readability of our code, and maximize the efficiency of our development efforts. We believe that ApeWorx's advanced features and flexibility will allow us to build high-quality smart contracts that meet our specific needs and requirements.<\/p>\n\n<p>To begin using ApeWorx for this project, you will need to have Python installed along with a virtual environment. You can set up these prerequisites by following the links provided.<\/p>\n\n<ul>\n<li><a href=\"https:\/\/www.python.org\/\">Python<\/a><\/li>\n<li><a href=\"https:\/\/academy.apeworx.io\/getting-started#install\">ApeWorx<\/a><\/li>\n<\/ul>\n\n<p>If you are new to this process, do not be intimidated. The setup process is simple, and we are confident that you will be able to get started quickly. With the necessary tools in place, we can begin leveraging ApeWorx's powerful features to build robust and reliable smart contracts.<\/p>\n\n<p>To start creating our project, we first need to create a new folder called <strong>uviswap<\/strong> and navigate to it using the terminal:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span><span class=\"nb\">mkdir <\/span>uviswap\n<span class=\"nv\">$ <\/span><span class=\"nb\">cd<\/span> .\/uviswap\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now we need to create a <a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\">Python Virtual Enviroment<\/a>, this is to keep our dependencies isolated from other packages. And we install our packages, in this case, we just need to install <a href=\"https:\/\/academy.apeworx.io\/getting-started#install\">ApeWorx<\/a>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>python3 <span class=\"nt\">-m<\/span> venv .venv\n<span class=\"nv\">$ <\/span><span class=\"nb\">source<\/span> .venv\/bin\/activate\n<span class=\"nv\">$ <\/span>pip <span class=\"nb\">install <\/span>eth-ape\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Next, we will initialize a new ApeWorx project and name it <strong>uviswap<\/strong>:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape init\n<span class=\"nv\">$ <\/span>Please enter project name: uviswap\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<blockquote>\n<p>\ud83d\udea7 If you encounter the issue of <code>No module named 'pkg_resources'<\/code>, you need to run <code>pip install setuptools<\/code> to fix it.<\/p>\n<\/blockquote>\n\n<p>Finally, we need to install Vyper as a plugin so that we can work with it using ApeWorx. Fortunately, the process is straightforward to understand, and can be accomplished using a single command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape plugins <span class=\"nb\">install <\/span>vyper\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Great! With our project now set up, we can move on to implementing the smart contracts.<\/p>\n\n<h2>\n  \n  \n  Smart contract development\n<\/h2>\n\n<p>For this DeFi application, we will define two smart contracts: the Pair and the Factory.<\/p>\n\n<ul>\n<li><p>The <strong>Pair<\/strong> contract is the heart of our automated market maker project and will be responsible for holding a pair of tokens.<\/p><\/li>\n<li><p>The <strong>Factory<\/strong> contract will be responsible for creating new pairs using new tokens or returning the address of a pair if it already exists.<\/p><\/li>\n<\/ul>\n\n<p>Together, these contracts will form the backbone of our DeFi application and allow us to implement our automated market-maker model.<\/p>\n\n<h3>\n  \n  \n  UviswapPair\n<\/h3>\n\n<p>To begin implementing the Pair contract, we will create a new file named <strong>UviswapPair.vy<\/strong> in the <strong>contracts\/<\/strong> directory. We will specify the Vyper version as <strong>^0.3.10<\/strong> and import the ERC20 and ERC20 Detailed interfaces from Vyper.<\/p>\n\n<p>This boilerplate code will provide us with the basic foundation for developing our Pair contract.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># pragma version ^0.3.10\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This is our basic boilerplate, we need the ERC20 definition to allow our users to use their shares however they want.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># pragma version ^0.3.10\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"c1\">###### EVENTS ######\n<\/span>\n<span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"c1\">###### STATE ######\n<\/span>\n<span class=\"c1\"># Share token name\n<\/span><span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># Share token symbol\n<\/span><span class=\"n\">symbol<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># Share token decimals\n<\/span><span class=\"n\">decimals<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint8<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter\n# method to allow access to account balances.\n<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># By declaring `allowance` as public, vyper automatically generates the `allowance()` getter\n<\/span><span class=\"n\">allowance<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># By declaring `totalSupply` as public, we automatically create the `totalSupply()` getter\n<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\">###### CONSTRUCTOR ######\n<\/span><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">symbol<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">UVI<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">decimals<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">18<\/span>\n\n\n<span class=\"c1\">###### INTERNAL METHODS ######\n<\/span><span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">ERC20: mint to the zero address<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">ERC20: burn to the zero address<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">ERC20: transfer to the zero address<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">][<\/span><span class=\"n\">_spender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Approval<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This code is the implementation of the Uviswap Pair smart contract, which represents a liquidity pool that holds two tokens. The Pair contract is written in Vype and uses two ERC20 interfaces - ERC20 and ERC20Detailed - to define the basic functionality and properties of a token.<\/p>\n\n<p>The code defines the following state variables:<\/p>\n\n<ul>\n<li>\n<strong>name<\/strong>: the name of the share token<\/li>\n<li>\n<strong>symbol<\/strong>: the symbol of the share token<\/li>\n<li>\n<strong>decimals<\/strong>: the number of decimal places for the share token<\/li>\n<li>\n<strong>balanceOf<\/strong>: a mapping of addresses to their token balances<\/li>\n<li>\n<strong>allowance<\/strong>: a mapping of addresses to their approved spending limits<\/li>\n<li>\n<strong>totalSupply<\/strong>: the total number of tokens in circulation<\/li>\n<\/ul>\n\n<p>The constructor sets the initial values for the name, symbol, and decimal state variables.<\/p>\n\n<p>The code also defines several internal and external methods:<\/p>\n\n<ul>\n<li>\n<strong>_mint<\/strong>: an internal method used to mint new tokens and update the balances of the token holder and the total supply<\/li>\n<li>\n<strong>_burn<\/strong>: an internal method used to burn existing tokens and update the balances of the token holder and the total supply<\/li>\n<li>\n<strong>transfer<\/strong>: an external method used to transfer tokens between accounts and update their balances<\/li>\n<li>\n<strong>transferFrom<\/strong>: an external method used to transfer tokens between accounts with the approval of the token holder and update their balances<\/li>\n<li>\n<strong>approve<\/strong>: an external method used to approve a third-party spender to use the tokens on behalf of the token holder<\/li>\n<li>\n<strong>burn<\/strong>: an external method used to burn tokens from the caller's account and update their balance<\/li>\n<\/ul>\n\n<p>Finally, the code defines two events, Transfer and Approval, that are emitted when tokens are transferred or approved for spending. The smart contract is divided on:<\/p>\n\n<ul>\n<li><strong>EVENTS<\/strong><\/li>\n<li><strong>STATE<\/strong><\/li>\n<li><strong>INTERNAL METHODS<\/strong><\/li>\n<li><strong>EXTERNAL METHODS<\/strong><\/li>\n<\/ul>\n\n<blockquote>\n<p>\ud83d\udc0d\u26a0\ufe0f This part is important since we are going to jump between those. So take note so you don't get lost.<\/p>\n<\/blockquote>\n\n<p>In addition to the ERC20 functionality, we need to add some state variables to our smart contract to implement the AMM functionality. These state variables include the two tokens in the pair and the corresponding reserves for each token. We will also define the invariant constant k, which is the product of the two reserves and is constant in a balanced pair:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"c1\"># Tokens in the pair\n<\/span><span class=\"n\">token0<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">token1<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># Reserves for each token\n<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">reserve1<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To enable our pool to track the tokens it handles and the amount of reserves available for each token, we need to add the token variables and reserve variables to our smart contract. These variables will be used to keep track of the balances for each token and the amount of liquidity in the pool.<\/p>\n\n<p>We also need to create an internal update method to keep track of the reserves each time we add or remove liquidity. This method will be called internally every time liquidity is added or removed from the pool and will update the reserves accordingly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### INTERNAL METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">_reserve0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_reserve1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve0<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve1<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To set up the Pair, we need to add a setup function that initializes the tokens and reserves. To ensure that it can only be called once, we'll add a flag variable that will be set to true once the setup is complete. This function will be called by the Factory when a new Pair is created.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"c1\"># Setup flag\n<\/span><span class=\"n\">_setup<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Since the method will be called from the outside we need to define it in the external methods section.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_setup<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">False<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Pair: already initialized<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token0<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token1<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_setup<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">True<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Add liquidity\n<\/h3>\n\n<p>The addLiquidity method is responsible for allowing users to deposit tokens into our smart contract, which is necessary for the AMM to function. When a user deposits tokens, the smart contract mints some share tokens in return. These share tokens can be redeemed later along with some collected fees resulting from other users swapping tokens with this liquidity.<\/p>\n\n<p>To prevent bad actors from exploiting this functionality, we added a reentrancy guard.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"nd\">@nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">add<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># add liquidity\n<\/span>    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># keep the pool balanced (k=x*y)\n<\/span>    <span class=\"k\">if<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">or<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">assert<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Pair: x \/ y != dx \/ dy<\/span><span class=\"sh\">\"<\/span> \n\n    <span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">isqrt<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">min<\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n        <span class=\"p\">)<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">shares<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Pair: shares were zero<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"c1\"># mint shares to liquidity provider\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">shares<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">),<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">shares<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This code is defining the <code>addLiquidity<\/code> in Vyper. <\/p>\n\n<p>The <code>@external<\/code> decorator indicates that this function can be called externally. The <code>@nonreentrant(\"add\")<\/code> decorator prevents reentrancy attacks on the function.<\/p>\n\n<p>When a user calls this function, they must pass in two arguments <code>_amount0<\/code> and <code>_amount1<\/code>, which represent the amount of token0 and token1 they want to add to the liquidity pool. <\/p>\n\n<p>First, the function transfers <code>_amount0<\/code> and <code>_amount1<\/code> from the sender to the smart contract using the <code>transferFrom<\/code> method of the <code>ERC20<\/code> token contract.<\/p>\n\n<p>Next, the function checks if the reserves of token0 and token1 are greater than 0. <a href=\"https:\/\/chain.link\/education-hub\/what-is-an-automated-market-maker-amm\">If they are, it verifies that the new reserves maintain the constant product <strong>(k=x*y)<\/strong>, which is necessary for the AMM to function properly.<\/a> If the new reserves do not maintain this constant product, an assertion error is raised.<\/p>\n\n<p>The function then calculates the amount of shares to mint for the liquidity provider, based on the amount of tokens they deposited, the current reserves, and the total supply of shares already in circulation. If this is the first liquidity deposit, the function sets the initial shares based on the square root of the product of the deposited token amounts. <\/p>\n\n<p>If the calculation of shares results in a value of 0, an assertion error is raised. <\/p>\n\n<p>The function then mints the calculated amount of shares to the liquidity provider and updates the reserves using the <code>_update<\/code> method and the function returns the amount of shares minted to the liquidity provider.<\/p>\n\n<h3>\n  \n  \n  Remove liquidity\n<\/h3>\n\n<p>To remove liquidity from the pool, the user needs to call the <code>removeLiquidity<\/code> function, passing the number of shares to burn. In exchange for burning the shares, the user will receive a proportional amount of the tokens that were originally deposited into the pool.<\/p>\n\n<p>The code for the <code>removeLiquidity<\/code> function is as follows:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"nd\">@nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">remove<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">bal0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token0<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">bal1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal0<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n    <span class=\"n\">amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal1<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n\n    <span class=\"c1\"># _burn checks if the user has enough shares\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_shares<\/span><span class=\"p\">)<\/span>\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">bal0<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">bal1<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># transfers the tokens back\n<\/span>    <span class=\"n\">_token0<\/span><span class=\"p\">.<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">_token1<\/span><span class=\"p\">.<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"nf\">return <\/span><span class=\"p\">(<\/span><span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>First, the function calculates the proportional amounts of each token based on the number of shares being burned. It then burns the shares that the user passed in and transfers the proportional amounts of each token back to the user. Finally, it updates the reserves to reflect the removed liquidity.<\/p>\n\n<p>As with the <code>addLiquidity<\/code> function, a reentrancy guard has been added to prevent reentrancy attacks.<\/p>\n\n<h3>\n  \n  \n  Swap\n<\/h3>\n\n<p>The swap function is a critical feature of any automated market maker. In this function, a user provides a token and an amount, and based on these inputs, we return the opposite token of the pair along with the corresponding amount. In the process, we charge a small fee to compensate our liquidity providers.<\/p>\n\n<p>To protect against malicious actors exploiting this feature, we have added a reentrancy guard.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"nd\">@nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">swap<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"ow\">or<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Pair: invalid token<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_amountIn<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Pair: amount in is zero<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"c1\"># variables to interact with the liquidity pool\n<\/span>    <span class=\"n\">tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">reserveIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"n\">reserveOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n    <span class=\"c1\"># determine which token is being swapped in\n<\/span>    <span class=\"c1\"># and assigning variables accordingly\n<\/span>    <span class=\"n\">isToken0<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">isToken0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n\n    <span class=\"c1\"># transfer in the tokens\n<\/span>    <span class=\"n\">tokenIn<\/span><span class=\"p\">.<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># 0.3% fee\n<\/span>    <span class=\"n\">amountInWithFee<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_amountIn<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">997<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">1000<\/span>\n\n    <span class=\"c1\"># calculate tokens to transfer\n<\/span>    <span class=\"n\">amountOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveOut<\/span> <span class=\"o\">*<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveIn<\/span> <span class=\"o\">+<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">.<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amountOut<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">),<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"c1\"># transfer in the tokens\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">amountOut<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The function allows a user to swap a given token for its counterpart in the pair by calling the method with the token address and the amount to be swapped.<\/p>\n\n<p>The function first checks whether the token being swapped is one of the tokens in the pair, and whether the amount being swapped is greater than zero. If either of these conditions fails, the function will not execute.<\/p>\n\n<p>Next, determines which token in the pair is being swapped in, and assigns variables accordingly. It then transfers the input token from the user to the contract.<\/p>\n\n<p>Then calculates the fee for the swap, which is 0.3% of the input amount, and calculates the corresponding amount of the output token to transfer back to the user based on the current reserves in the pool.<\/p>\n\n<p>Finally, it transfers the output tokens to the user, updates the reserves, and returns the amount of output tokens transferred.<\/p>\n\n<p><a href=\"https:\/\/gist.github.com\/rafael-abuawad\/6b4b443b578125e1e9e19e5afe078246\">\ud83e\udd84 You can find the complete UviswapPair smart-contract here.<\/a><\/p>\n\n<h3>\n  \n  \n  UviswapFactory\n<\/h3>\n\n<p>To begin implementing the Factory contract, we will create a new file named <strong>UviswapFactory.vy<\/strong> in the <strong>contracts<\/strong> directory and specify the Vyper version as 0.3.10. This smart contract will be responsible for creating liquidity pools that use two tokens that can be provided by users.<\/p>\n\n<p>The code for our initial implementation should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># pragma version ^0.3.10\n<\/span>\n<span class=\"c1\">###### INTERFACES ######\n<\/span>\n<span class=\"c1\">###### STATE ######\n<\/span>\n<span class=\"c1\">###### CONSTRUCTOR ######\n<\/span>\n<span class=\"c1\">###### METHODS ######\n<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The following code block defines an interface for the UviswapPair smart contract. This interface only includes one method, setup, which we will use to create a new liquidity pool.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"bp\">...<\/span>\n<span class=\"c1\">###### INTERFACES ######\n<\/span>\n<span class=\"n\">interface<\/span> <span class=\"n\">UviswapPair<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">def<\/span> <span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span> <span class=\"n\">nonpayable<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This interface declares the method signature for the setup function that takes two parameters, <code>_token0<\/code> and <code>_token1<\/code> of type <code>address<\/code>, representing the two tokens that will be used in the liquidity pool. The <code>nonpayable<\/code> modifier ensures that this method does not accept any Ether as payment.<\/p>\n\n<p>Next, we'll declare the state of the smart contract. We need to map the token pairs that we have created and add an array to store each one of them. Additionally, we need to declare a master pair contract address, which will be used as a blueprint by Vyper to create and deploy new pair smart contracts.<\/p>\n\n<p>Here's the code:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"c1\"># Pair Contract =&gt; Token &lt;=&gt; Token\n<\/span><span class=\"n\">getPair<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">address<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># All pairs list\n<\/span><span class=\"n\">allPairs<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">DynArray<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"mi\">30<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># Uviswap Pair contract address used to create clones of it\n<\/span><span class=\"n\">pairContract<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After declaring the state variables, we can define the constructor function. This function is important because it allows us to pass the address of an empty pair smart contract that we must deploy before we deploy this one.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### CONSTRUCTOR ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">(<\/span><span class=\"n\">_pairContract<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">pairContract<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_pairContract<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>That would be everything we need before defining the main <em>createPair<\/em> method, which will allow our users to create a token pair freely.<\/p>\n\n<h3>\n  \n  \n  Create pair\n<\/h3>\n\n<p>The create pair method is simple, we pass in two tokens, token A and token B., with these two tokens we deploy a new pair smart contract (using the <em>pairContract<\/em> state variable we defined in the constructor) and we add to the pairs mapping and the pairs array, and that's it!<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### METHODS ######\n<\/span><span class=\"bp\">...<\/span>\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">address<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenA<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Factory: identical addresses<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenA<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">_tokenB<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Factory: zero address<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span>  <span class=\"sh\">\"<\/span><span class=\"s\">Uviswap Factory: pair exists<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"c1\"># create pair smart contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">create_forwarder_to<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">pairContract<\/span><span class=\"p\">)<\/span>\n    <span class=\"nc\">UviswapPair<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">).<\/span><span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># populate mapping in, and in the reverse direction\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span>\n\n    <span class=\"c1\"># append pair to all pairs array\n<\/span>    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allPairs<\/span><span class=\"p\">.<\/span><span class=\"nf\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">pair<\/span>\n\n<span class=\"bp\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><a href=\"https:\/\/gist.github.com\/rafael-abuawad\/2be10524447656b81cd0893fc2bca418\">\ud83e\udd84 You can find the complete Uviswap Factory smart-contract here.<\/a><\/p>\n\n<h2>\n  \n  \n  Testing\n<\/h2>\n\n<p>Now, we need to cover the testing section, which is a crucial part of our application. In this section, we will cover the basics of token swaps and liquidity addition. To begin with, we need to deploy mock smart contracts for testing, and for that, we will use Vyper's official example.<\/p>\n\n<blockquote>\n<p>\ud83d\udea7 To do this, we need to create a <strong>mocks\/<\/strong> folder inside the <strong>contracts\/<\/strong> folder, and within it, create an <strong>Token.vy<\/strong> file. You can add the code from the following link to this file: <a href=\"https:\/\/github.com\/vyperlang\/vyper\/blob\/master\/examples\/tokens\/ERC20.vy\">Vyper ERC20 Token<\/a>.<\/p>\n\n<p>\ud83d\udc0d\u26a0\ufe0f It is important to note that while the current testing strategy covers the basics, it is not sufficient for production. It is recommended to conduct thorough testing that includes fuzz testing and stateful testing before deploying an application to production.<\/p>\n<\/blockquote>\n\n<p>After setting up the necessary mock smart contracts, we will create a <strong>conftest.py<\/strong> file inside the <strong>tests<\/strong> folder. This file will be used to define reusable elements such as fixtures, which act like functions that return a new deployment each time to test our application. For testing our automated market maker, we will only need two demo tokens.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">import<\/span> <span class=\"n\">pytest<\/span>\n\n\n<span class=\"nd\">@pytest.fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"sh\">\"<\/span><span class=\"s\">function<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">usdt_token<\/span><span class=\"p\">(<\/span><span class=\"n\">project<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"sh\">\"\"\"<\/span><span class=\"s\">\n    Returns a new instance of a mock USDT token contract, with an initial supply of 1,000.\n    <\/span><span class=\"sh\">\"\"\"<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">Token<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">USDT<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">USDT<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">18<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1000<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n\n<span class=\"nd\">@pytest.fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"sh\">\"<\/span><span class=\"s\">function<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">usdc_token<\/span><span class=\"p\">(<\/span><span class=\"n\">project<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"sh\">\"\"\"<\/span><span class=\"s\">\n    Returns a new instance of a mock USDC token contract, with an initial supply of 1,000.\n    <\/span><span class=\"sh\">\"\"\"<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">Token<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">USDC<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">USDC<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">18<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1000<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n\n<span class=\"nd\">@pytest.fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"sh\">\"<\/span><span class=\"s\">function<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">uviswap_pair<\/span><span class=\"p\">(<\/span><span class=\"n\">project<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"sh\">\"\"\"<\/span><span class=\"s\">\n    Returns a new instance of an empty Pair contract, primarily to be used as a blueprint.\n    <\/span><span class=\"sh\">\"\"\"<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n\n<span class=\"nd\">@pytest.fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"sh\">\"<\/span><span class=\"s\">function<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">uviswap_factory<\/span><span class=\"p\">(<\/span><span class=\"n\">project<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_pair<\/span><span class=\"p\">):<\/span>\n    <span class=\"sh\">\"\"\"<\/span><span class=\"s\">\n    Returns a new instance of a Factory contract, the main entry point of our AMM.\n    <\/span><span class=\"sh\">\"\"\"<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapFactory<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">uviswap_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The code defines four fixtures: <code>usdt_token<\/code>, <code>usdc_token<\/code>, <code>uviswap_pair<\/code>, and <code>uviswap_factory<\/code>. <\/p>\n\n<p>The <code>uviswap_pair<\/code> fixture creates and deploys a new instance of the <code>UviswapPair<\/code> contract.<\/p>\n\n<p>The <code>uviswap_factory<\/code> fixture creates and deploys a new instance of the <code>UviswapFactory<\/code> contract, which requires the address of an empty <code>UviswapPair<\/code> contract as an argument. In this case, the address of the <code>uviswap_pair<\/code> fixture is used as the argument for the <code>UviswapFactory<\/code> deployment.<\/p>\n\n<p>To test the functionality that we defined earlier, we will create a file called <strong>test_uviswap.py<\/strong> inside the <strong>tests<\/strong> folder. At the top of this file, we should import <code>project<\/code> from Ape. This allows us to access the contracts on some of the tests.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">from<\/span> <span class=\"n\">ape<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">project<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  \ud83e\uddea Creating a Liquidity Pool\n<\/h3>\n\n<p>The test creates a new pair contract by calling the <code>createPair<\/code> function of the <code>uviswap_factory<\/code> contract and passing the addresses of two tokens as arguments. It then retrieves the address of the created pair contract and uses it to instantiate a new UviswapPair object. Finally, it asserts that the <code>UviswapPair<\/code> object has the expected default values for its <code>token0<\/code>, <code>token1<\/code>, <code>reserve0<\/code>, <code>reserve1<\/code>, and <code>totalSupply<\/code> variables.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_create_pair<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># Create a new pair contract by calling the method with the addresses of two tokens\n<\/span>    <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> \n\n    <span class=\"c1\"># Access the address of the created pair contract\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">allPairs<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Access the pair contract object by its address\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Assert that the pair contract object has the expected default values\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">token0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">token1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">totalSupply<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  \ud83e\uddea Adding liquidity to the Pool\n<\/h3>\n\n<p>This code is testing the functionality of creating a new pair contract, adding liquidity to the contract, and checking if all the values are set correctly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_add_liquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># Create a new pair contract by calling the method with the addresses of two tokens\n<\/span>    <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> \n\n    <span class=\"c1\"># Access the address of the created pair contract\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">allPairs<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Access the pair contract object by its address\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Define the amount to add liquidity to the pair contract (500 USDC\/USDT)\n<\/span>    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">500e18<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Approve pair to use our tokens\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Add liquidity to the pair contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Check if the liquidity is added correctly\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span> <span class=\"c1\"># minted shares\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  \ud83e\uddea Removing liquidity from the Pool\n<\/h3>\n\n<p>This code tests the functionality of creating a new pair contract, adding liquidity to the contract, then removing value from the contract and checking if all the values are set correctly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_remove_liquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># Create a new pair contract by calling the method with the addresses of two tokens\n<\/span>    <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> \n\n    <span class=\"c1\"># Access the address of the created pair contract\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">allPairs<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Access the pair contract object by its address\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Define the amount to add liquidity to the pair contract (500 USDC\/USDT)\n<\/span>    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">500e18<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Approve pair to use our tokens\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Add liquidity to the pair contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Get the number of shares owned by the account\n<\/span>    <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Remove liquidity from the pair\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Assert that the pool reserves and token balances are now all zero\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span> <span class=\"c1\"># confirm shares have been removed\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  \ud83e\uddea Swapping assets\n<\/h3>\n\n<p>This code is testing the <code>swap()<\/code> function of the pair contract. The code creates a new pair contract with mock USDT and USDC tokens, adds liquidity to it, and then performs a swap of 100 USDT for USDC. The balances of the accounts before and after the swap are compared to ensure the swap was performed correctly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_swap<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># Create a new pair contract by calling the method with the addresses of two tokens\n<\/span>    <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> \n\n    <span class=\"c1\"># Access the address of the created pair contract\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">allPairs<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Access the pair contract object by its address\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Define the amount to add liquidity to the pair contract (500 USDC\/USDT)\n<\/span>    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">500e18<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Approve pair to use our tokens\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Add liquidity to the pair contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Save the initial balances before the swap\n<\/span>    <span class=\"n\">initial_balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># Define the amount to be swapped for the other token on the pair contract (100 USDT)\n<\/span>    <span class=\"n\">swap_amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">100e18<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Approve token for a swap\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Perform the swap\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Get the balances after the swap\n<\/span>    <span class=\"n\">final_balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># Test that we swapped tokens correctly\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">-<\/span> <span class=\"n\">swap_amount<\/span> <span class=\"o\">==<\/span> <span class=\"n\">final_balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"c1\"># USDT balance should decrease (initial - swapped amount)\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">final_balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"c1\"># USDC balance should increase\n<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  \ud83e\uddea Collecting fees\n<\/h3>\n\n<p>This code is testing the <code>removeLiquidity()<\/code> function of the pair contract. The code creates a new pair contract with mock USDT and USDC tokens, adds liquidity to it, and then performs a swap of 10 USDT for USDC. The balances of the accounts before and after the swap are compared to ensure the swap was performed correctly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_collecting_fees<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># Create a new pair contract by calling the method with the addresses of two tokens\n<\/span>    <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> \n\n    <span class=\"c1\"># Access the address of the created pair contract\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">uviswap_factory<\/span><span class=\"p\">.<\/span><span class=\"nf\">allPairs<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Access the pair contract object by its address\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># Define the amount to add liquidity to the pair contract (100 USDC\/USDT)\n<\/span>    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">100e18<\/span><span class=\"p\">)<\/span> \n\n    <span class=\"c1\"># Approve pair to use our tokens\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Add liquidity to the pair contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Save the initial balances before the swap\n<\/span>    <span class=\"n\">balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># Define the amount to be swapped for the other token on the pair contract (10 USDT)\n<\/span>    <span class=\"n\">swap_amount<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">10e18<\/span><span class=\"p\">)<\/span>  \n\n    <span class=\"c1\"># Approve token for a swap\n<\/span>    <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Perform the swap\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Get shares\n<\/span>    <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">shares<\/span> <span class=\"o\">==<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">100e18<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># shares received should be equal to the amount of liquidity added\n<\/span>\n    <span class=\"c1\"># Remove liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># Get the balances after claiming all the shares\n<\/span>    <span class=\"n\">balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># Test that we collected fees correctly\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdt<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">1000e18<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># USDT balance should be the original mint\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">usdc<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"nf\">int<\/span><span class=\"p\">(<\/span><span class=\"mf\">1000e18<\/span><span class=\"p\">)<\/span> <span class=\"c1\"># USDC balance should be the original mint\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span> <span class=\"c1\"># confirm shares have been removed\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"nf\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdc_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">usdt_token<\/span><span class=\"p\">.<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This concludes the testing process for the smart contracts. Run the <code>ape test<\/code> on the terminal to execute the tests on a local network.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape <span class=\"nb\">test<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>We defined several tests for the smart contracts that were implemented in the project. These tests cover various functionalities, including adding and removing liquidity, swapping tokens, and collecting fees. Each test is written in a way that clearly describes the functionality being tested and sets up the necessary conditions to execute the test.<\/p>\n\n<p>You can extend the tests to cover additional scenarios because the current set of tests is not exhaustive.<\/p>\n\n<p><a href=\"https:\/\/gist.github.com\/rafael-abuawad\/9a42892410770480435b1974b39bdc79\">\ud83e\uddea You can find the complete <code>test_uviswap.py<\/code> file here.<\/a><\/p>\n\n<h2>\n  \n  \n  Scripts\n<\/h2>\n\n<p>We'll be adding a deploy script to make it easy to deploy our application to any blockchain. For this demonstration, we'll be deploying to Avalanche, and thanks to ApeWorx, the process is incredibly simple. <a href=\"https:\/\/github.com\/ApeWorX\/ape-avalanche\">All we need to do is install the official Avalanche plugin provided by ApeWorx.<\/a><\/p>\n\n<p>In this case, since we'll be deploying our Uviswap App to Avalanche, we'll need to install the Avalanche plugin. You can easily do this by running the command on your terminal:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape plugins <span class=\"nb\">install <\/span>avalanche\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, we need to configure the RPC URL endpoints ape is going to connect to, this can be done on the <code>ape-config.yaml<\/code> file, yours should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"c1\"># ape-config.yaml<\/span>\n<span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">uviswap<\/span>\n\n<span class=\"na\">plugins<\/span><span class=\"pi\">:<\/span>\n  <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">avalanche<\/span>\n  <span class=\"pi\">-<\/span> <span class=\"na\">name<\/span><span class=\"pi\">:<\/span> <span class=\"s\">vyper<\/span>\n\n<span class=\"na\">geth<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">avalanche<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">mainnet<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">uri<\/span><span class=\"pi\">:<\/span> <span class=\"s\">https:\/\/api.avax.network\/ext\/bc\/C\/rpc<\/span>\n    <span class=\"na\">fuji<\/span><span class=\"pi\">:<\/span>\n      <span class=\"na\">uri<\/span><span class=\"pi\">:<\/span> <span class=\"s\">https:\/\/avalanche-fuji.drpc.org\/<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>It's worth noting that plugins are a great way to expand the functionality of ApeWorx.<\/p>\n\n<h3>\n  \n  \n  Accounts\n<\/h3>\n\n<p>To deploy our smart contracts, we'll need an account with AVAX <a href=\"https:\/\/core.app\/en\/tools\/testnet-faucet\/\">(if you are on testnet you can fund your wallet using the official faucet)<\/a>. While many frameworks suggest adding your private key to a <code>.env<\/code> file, this approach can be a serious security vulnerability. Luckily, ApeWorx provides a better solution out of the box that allows us to work with accounts more securely.<\/p>\n\n<p>With ApeWorx, all we need to do is execute a few simple commands to get set up. We won't have to worry about storing our private key in a file or exposing it to potential attackers. This way, we can work with our accounts and deploy our smart contracts with confidence and peace of mind. Let's dive in and get started!<\/p>\n\n<blockquote>\n<p>For this guide I will be using the name <code>test_account<\/code> to deploy the smart contract, you can choose any name you like, but be sure to use the same name on your <em>script<\/em>.<br>\n<\/p>\n<\/blockquote>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape accounts generate &lt;name_of_your_account&gt;\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This will prompt you to put in your <code>private key<\/code> and a <code>password<\/code>, you can get your private key from MetaMask or any other wallet that you are using, and the password is going to be used to encrypt your account.<\/p>\n\n<p>After we complete that inside your <em>scripts<\/em> folder create a  <em>deploy.py<\/em>, this is going to hold the code for our deployments.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code>\n<span class=\"kn\">from<\/span> <span class=\"n\">ape<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">project<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">main<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">test_account<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">.<\/span><span class=\"nf\">load<\/span><span class=\"p\">(<\/span><span class=\"sh\">\"<\/span><span class=\"s\">test_account<\/span><span class=\"sh\">\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">uviswap_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapPair<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">test_account<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">project<\/span><span class=\"p\">.<\/span><span class=\"n\">UviswapFactory<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">uviswap_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">sender<\/span><span class=\"o\">=<\/span><span class=\"n\">test_account<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>That would be it, just type <code>ape run deploy --network &lt;network&gt;<\/code> and Ape will run the deploy script.<\/p>\n\n<p>Command to deploy on Avalanche Tesnet<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape run deploy <span class=\"nt\">--network<\/span> avalanche:fuji\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Command to deploy on Avalanche Mainnet<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape run deploy <span class=\"nt\">--network<\/span> avalanche:mainnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Conclusion\n<\/h2>\n\n<p>Automatic Market Makers are a wonderful tool used in the decentralized finance space, it allows users to swap tokens without \"normal\" market makers almost instantly. These kinds of smart contracts have a lot of use cases, and you can expand a lot more on this automatic market maker idea. Be creative!<\/p>\n\n\n\n\n<h2>\n  \n  \n  Uviswap GitHub Repository\n<\/h2>\n\n<p>Explore Uviswap on GitHub: <a href=\"https:\/\/github.com\/rafael-abuawad\/uviswap\">https:\/\/github.com\/rafael-abuawad\/uviswap<\/a><\/p>\n\n<p>Discover the complete source code, smart contracts, testing scripts, and deployment instructions. Contribute, open issues, and engage with the community.<\/p>\n\n","category":["web3","blockchain","python","vyper"]},{"title":"Challenge #2: \ud83e\ude99 Multi Token Vendor | Speedrun Ethereum With Vyper","pubDate":"Thu, 09 Mar 2023 14:32:39 +0000","link":"https:\/\/dev.to\/rabuawad\/challenge-3-multi-token-vendor-speedrun-ethereum-with-vyper-230p","guid":"https:\/\/dev.to\/rabuawad\/challenge-3-multi-token-vendor-speedrun-ethereum-with-vyper-230p","description":"<h2>\n  \n  \n  Table of contents\n<\/h2>\n\n<ul>\n<li>\ud83e\ude99 Introduction<\/li>\n<li>\ud83d\udce6 Setup<\/li>\n<li>\ud83d\udcd1 Code<\/li>\n<li>\ud83d\udd2c Conclusion<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  \ud83e\ude99 Introductionn <a><\/a>\n<\/h2>\n\n<p>ERC1155 is a novel token standard that draws inspiration from previous standards like ERC20, ERC721, and ERC777 to create a more efficient and fungibility-agnostic token contract. This standard is designed to be gas-efficient and allow for the creation of multiple token types within a single contract, which can significantly reduce transaction costs and increase flexibility for developers.<\/p>\n\n<p>By taking the best ideas from previous standards, ERC1155 aims to provide a more streamlined and versatile approach to token development. If you're not already familiar with ERC20, ERC721, and ERC777, it's worth reviewing their guides to better understand the context and benefits of ERC1155. Overall, this standard represents an exciting step forward in token development and has the potential to unlock new possibilities for DeFi and other blockchain applications.<\/p>\n\n<h2>\n  \n  \n  \ud83d\udce6 Setup <a><\/a>\n<\/h2>\n\n<p>For setting up the project on a local machine, only one essential component is required: <\/p>\n\n<ul>\n<li><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer\">Python<\/a><\/li>\n<\/ul>\n\n<p><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer\">Python<\/a> is the primary programming language used in the project, it includes <a href=\"https:\/\/pypi.org\/project\/pip\/\" rel=\"noopener noreferrer\">PIP<\/a>, which serves as the package manager for Python and <a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\" rel=\"noopener noreferrer\">Virtual ENV<\/a> is an essential tool used for creating a virtual environment that will house the application's code.<\/p>\n\n<p>While the process for setting up these components is beyond the scope of this challenge, in essence, it involves installing Python and configuring a virtual environment for the application's code. It is important to note that creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, thereby improving stability and reproducibility.<\/p>\n\n<h3>\n  \n  \n  Brownie\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/eth-brownie.readthedocs.io\" rel=\"noopener noreferrer\">Brownie<\/a> in this challenge, in your <code>virtual environment<\/code>, <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/install.html\" rel=\"noopener noreferrer\">go ahead and install Brownie, after you installed it<\/a>, create a new folder called <code>vaults<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, you might want to use the Hardhat node to test our smart contracts, so inside your project folder, run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install<\/span> <span class=\"nt\">--save-dev<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  ApeWorx\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/docs.apeworx.io\/ape\/stable\/userguides\/quickstart.html#documentation\" rel=\"noopener noreferrer\">ApeWorx<\/a> in this challenge, activate your <code>virtual environment<\/code> and install ApeWorx:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>pip <span class=\"nb\">install <\/span>eth-ape<span class=\"s1\">'[recommended-plugins]'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After you installed it, create a new folder called <code>vaults<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  \ud83d\udcd1 Code <a><\/a>\n<\/h2>\n\n<p>The ERC-1155 standard is a novel token standard that aims to take the best from previous standards to create a fungibility-agnostic and gas-efficient token contract. ERC1155 draws ideas from all of ERC20, ERC721, and ERC777. Inside your <code>contracts<\/code> folder, create a file called <code>token.vy<\/code> this will contain all of the code necessary to implement the ERC-1155.<\/p>\n\n<h3>\n  \n  \n  Token (ERC-1155)\n<\/h3>\n\n<p>In this chanllege, there is no barebones implementation of the <code>1155<\/code> token standard in Vyper. Can you make it from scratch?<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.3\n<\/span>\n<span class=\"c1\"># ... missing ERC-1155 implementation\n<\/span><\/code><\/pre>\n\n<\/div>\n\n\n\n<blockquote>\n<p><strong>Important<\/strong>: \u26a0\ufe0f\ud83d\udc0d If you are new to Vyper, don't worry, it was designed to be simple and readable, making it easier for programmers with any level of experience to quickly grasp the language. If you need more guidance, there are many resources available online to help you get started, such as the Vyper <a href=\"https:\/\/docs.vyperlang.org\/en\/stable\/vyper-by-example.html\" rel=\"noopener noreferrer\">documentation<\/a>, <a href=\"https:\/\/vyper-by-example.org\/\" rel=\"noopener noreferrer\">tutorials<\/a>, and community forums.<\/p>\n\n<p>Feel stuck? Take a look at the <a href=\"https:\/\/github.com\/vyperlang\/vyper\/blob\/master\/examples\/tokens\/ERC1155ownable.vy\" rel=\"noopener noreferrer\">Vyperlang Official Implemenation<\/a><\/p>\n<\/blockquote>\n\n<h2>\n  \n  \n  \ud83d\udd2c Conclusion <a><\/a>\n<\/h2>\n\n<p>In this challenge, we have explored the ERC1155 token standard and its role as a fundamental building block of DeFi and NFT applications on EVM-compatible blockchains, and in conclusion, ERC1155 is a novel standard that combines the best ideas from previous standards like ERC20, ERC721, and ERC777 to create a more efficient and flexible token contract. By allowing for the creation of multiple token types within a single contract, ERC1155 can significantly reduce transaction costs and increase flexibility for developers.<\/p>\n\n<p>Finally, implementing the ERC1155 token standard in Vyper can be done from scratch by following the guidelines and resources provided. Overall, ERC1155 represents an exciting step forward in token development, and its potential to unlock new possibilities for DeFi and other blockchain applications makes it a standard worth exploring.<\/p>\n\n<blockquote>\n<p>\ud83d\udcd2 <strong>Note<\/strong>: Whether using <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/\" rel=\"noopener noreferrer\">Brownie<\/a> or <a href=\"https:\/\/www.apeworx.io\/\" rel=\"noopener noreferrer\">ApeWorx<\/a>, creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, improving stability and reproducibility.<\/p>\n<\/blockquote>\n\n\n\n<blockquote>\n<p>\ud83d\udc0d <strong>Note<\/strong>: The <a href=\"https:\/\/vyper.readthedocs.io\/\" rel=\"noopener noreferrer\">Vyper programming language<\/a> offers several advantages over other languages, including higher security, improved gas efficiency, and enhanced code readability, making it a great option for NFT development projects.<\/p>\n<\/blockquote>\n\n","category":["ai","openai","chatgpt","claude"]},{"title":"Challenge #1: \ud83e\udd69 Decentralized Staking App | Speedrun Ethereum With Vyper \ud83d\udc0d","pubDate":"Fri, 17 Feb 2023 15:16:42 +0000","link":"https:\/\/dev.to\/rabuawad\/challenge-1-decentralized-staking-app-speedrun-ethereum-with-vyper-17ba","guid":"https:\/\/dev.to\/rabuawad\/challenge-1-decentralized-staking-app-speedrun-ethereum-with-vyper-17ba","description":"<h2>\n  \n  \n  Table of contents\n<\/h2>\n\n<ul>\n<li>\ud83e\udd69 Introduction<\/li>\n<li>\ud83d\udce6 Setup<\/li>\n<li>\ud83d\udcd1 Code<\/li>\n<li>\ud83d\udd2c Conclusion<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  \ud83e\udd69 Introductionn <a><\/a>\n<\/h2>\n\n<p>The ERC20 standard has long been the backbone of token development on EVM-compatible blockchains, serving as a fundamental component not only for DeFi but for a wide range of blockchain applications. However, as the DeFi ecosystem continues to evolve, the need for new standards that can support more advanced features and functions has become increasingly apparent.<\/p>\n\n<p>ERC4626 is one such standard, specifically designed for yield-generating vaults. By providing a more consistent and interoperable framework for developing these critical components of DeFi, ERC4626 promises to open up new opportunities for developers and users alike.<\/p>\n\n<p>In the upcoming challenge, we will delve into the implementation process for both tokens and vaults, leveraging the Vyper programming language to explore the key concepts and principles involved in this exciting area of blockchain development. Through this process, participants will gain a deeper understanding of the challenges and opportunities involved in building DeFi applications, and be equipped with the skills and knowledge necessary to succeed in this dynamic and rapidly-evolving field.<\/p>\n\n<h2>\n  \n  \n  \ud83d\udce6 Setup <a><\/a>\n<\/h2>\n\n<p>For setting up the project on a local machine, only one essential component is required: <\/p>\n\n<ul>\n<li><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer\">Python<\/a><\/li>\n<\/ul>\n\n<p><a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer\">Python<\/a> is the primary programming language used in the project, it includes <a href=\"https:\/\/pypi.org\/project\/pip\/\" rel=\"noopener noreferrer\">PIP<\/a>, which serves as the package manager for Python and <a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\" rel=\"noopener noreferrer\">Virtual ENV<\/a> is an essential tool used for creating a virtual environment that will house the application's code.<\/p>\n\n<p>While the process for setting up these components is beyond the scope of this challenge, in essence, it involves installing Python and configuring a virtual environment for the application's code. It is important to note that creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, thereby improving stability and reproducibility.<\/p>\n\n<h3>\n  \n  \n  Brownie\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/eth-brownie.readthedocs.io\" rel=\"noopener noreferrer\">Brownie<\/a> in this challenge, in your <code>virtual environment<\/code>, <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/install.html\" rel=\"noopener noreferrer\">go ahead and install Brownie, after you installed it<\/a>, create a new folder called <code>vaults<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, you might want to use the Hardhat node to test our smart contracts, so inside your project folder, run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install<\/span> <span class=\"nt\">--save-dev<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  ApeWorx\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/docs.apeworx.io\/ape\/stable\/userguides\/quickstart.html#documentation\" rel=\"noopener noreferrer\">ApeWorx<\/a> in this challenge, activate your <code>virtual environment<\/code> and install ApeWorx:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>pip <span class=\"nb\">install <\/span>eth-ape<span class=\"s1\">'[recommended-plugins]'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After you installed it, create a new folder called <code>vaults<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  \ud83d\udcd1 Code <a><\/a>\n<\/h2>\n\n<p>The ERC-20 token standard serves as the foundation for DeFi applications on EVM blockchains. Inside your <code>contracts<\/code> folder, create a file called <code>token.vy<\/code> this will contain all of the code necessary to implement the ERC-20.<\/p>\n\n<h3>\n  \n  \n  Token (ERC-20)\n<\/h3>\n\n<p>Here is a barebones implementation of the <code>ERC20<\/code> token standard in Vyper, can you turn it into a working smart contract?<\/p>\n\n<blockquote>\n<p><strong>Important<\/strong>: \u26a0\ufe0f\ud83d\udc0d If you are new to Vyper, don't worry, it was designed to be simple and readable, making it easier for programmers with any level of experience to quickly grasp the language. If you need more guidance, there are many resources available online to help you get started, such as the Vyper <a href=\"https:\/\/docs.vyperlang.org\/en\/stable\/vyper-by-example.html\" rel=\"noopener noreferrer\">documentation<\/a>, <a href=\"https:\/\/vyper-by-example.org\/\" rel=\"noopener noreferrer\">tutorials<\/a>, and community forums.<br>\n<\/p>\n<\/blockquote>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.3\n<\/span><span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"c1\">### INTERFACES ###\n<\/span><span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"c1\">### EVENTS ###\n<\/span><span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"c1\">### METHODS ###\n<\/span><span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">name<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">10<\/span><span class=\"p\">]:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">NAME<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">symbol<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">5<\/span><span class=\"p\">]:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">SYMBOL<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">decimals<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint8<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">DECIMALS<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation \n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">False<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation \n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">False<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">False<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"c1\"># ... TODO: Security\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"c1\"># ... TODO: Security\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burnFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"c1\"># ... TODO: Security\n<\/span>    <span class=\"k\">pass<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<blockquote>\n<p>Feel stuck? Take a look at the <a href=\"https:\/\/github.com\/vyperlang\/vyper\/blob\/master\/examples\/tokens\/ERC20.vy\" rel=\"noopener noreferrer\">Vyperlang Official Implemenation<\/a><\/p>\n<\/blockquote>\n\n<p>Here is a barebones implementation of the <code>ERC4626<\/code> token standard in Vyper, can you turn it into a working smart contract?<\/p>\n\n<blockquote>\n<p><strong>Note<\/strong>: \ud83d\udca1 There are many ways to generate yield. <a href=\"https:\/\/solidity-by-example.org\/defi\/staking-rewards\/\" rel=\"noopener noreferrer\">Take a look at this one, implemented in Solidity<\/a><br>\n<\/p>\n<\/blockquote>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.3\n<\/span><span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC4626<\/span>\n\n<span class=\"c1\">### INTERFACES ####\n<\/span><span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC4626<\/span>\n\n<span class=\"c1\">#### ERC20 | EVENTS ####\n<\/span>\n<span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">allowance<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"c1\">#### ERC4626 | EVENTS ####\n<\/span>\n<span class=\"n\">event<\/span> <span class=\"n\">Deposit<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">depositor<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n    <span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Withdraw<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">withdrawer<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n    <span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n\n<span class=\"c1\">### METHODS ###\n<\/span><span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">name<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">10<\/span><span class=\"p\">]:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">NAME<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">symbol<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">5<\/span><span class=\"p\">]:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">SYMBOL<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">decimals<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint8<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">DECIMALS<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">totalAssets<\/span><span class=\"p\">()<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">convertToAssets<\/span><span class=\"p\">(<\/span><span class=\"n\">shareAmount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">convertToShares<\/span><span class=\"p\">(<\/span><span class=\"n\">assetAmount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">maxDeposit<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">previewDeposit<\/span><span class=\"p\">(<\/span><span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">deposit<\/span><span class=\"p\">(<\/span><span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">maxMint<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">previewMint<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">mint<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">maxWithdraw<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">previewWithdraw<\/span><span class=\"p\">(<\/span><span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">withdraw<\/span><span class=\"p\">(<\/span><span class=\"n\">assets<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">maxRedeem<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@view<\/span>\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">previewRedeem<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">redeem<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"o\">=<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<blockquote>\n<p>Feel stuck? Take a look at the <a href=\"https:\/\/github.com\/vyperlang\/vyper\/blob\/master\/examples\/tokens\/ERC4626.vy\" rel=\"noopener noreferrer\">Vyperlang Official Implemenation<\/a><\/p>\n<\/blockquote>\n\n<h2>\n  \n  \n  \ud83d\udd2c Conclusion <a><\/a>\n<\/h2>\n\n<p>In this challenge, we have explored the ERC20 token standard and its role as a fundamental building block of DeFi applications on EVM-compatible blockchains. We have learned how to use the Vyper programming language to create a basic implementation of the ERC20 standard, including the definition of token properties, the specification of events, and the implementation of essential token transfer methods.<\/p>\n\n<p>Going beyond this, we have also introduced the ERC4626 standard, which is specifically designed for yield-generating vaults. By providing a consistent and interoperable framework for the development of these critical DeFi components, ERC4626 offers a significant opportunity for developers and users alike to benefit from new features and functionality in the DeFi ecosystem.<\/p>\n\n<blockquote>\n<p>\ud83d\udcd2 <strong>Note<\/strong>: Whether using <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/\" rel=\"noopener noreferrer\">Brownie<\/a> or <a href=\"https:\/\/www.apeworx.io\/\" rel=\"noopener noreferrer\">ApeWorx<\/a>, creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, improving stability and reproducibility.<\/p>\n<\/blockquote>\n\n\n\n<blockquote>\n<p>\ud83d\udc0d <strong>Note<\/strong>: The <a href=\"https:\/\/vyper.readthedocs.io\/\" rel=\"noopener noreferrer\">Vyper programming language<\/a> offers several advantages over other languages, including higher security, improved gas efficiency, and enhanced code readability, making it a great option for NFT development projects.<\/p>\n<\/blockquote>\n\n","category":["webdev","career","productivity","discuss"]},{"title":"Challenge #0: \ud83d\uddbc\ufe0f Simple NFT Example | Speedrun Ethereum With Vyper \ud83d\udc0d","pubDate":"Wed, 15 Feb 2023 15:56:05 +0000","link":"https:\/\/dev.to\/rabuawad\/challenge-0-simple-nft-example-speedrun-ethereum-with-vyper-4n8m","guid":"https:\/\/dev.to\/rabuawad\/challenge-0-simple-nft-example-speedrun-ethereum-with-vyper-4n8m","description":"<h2>\n  \n  \n  Table of contents\n<\/h2>\n\n<ul>\n<li>\ud83c\udf9f Introduction<\/li>\n<li>\ud83d\udce6 Setup<\/li>\n<li>\ud83d\udcd1 Code<\/li>\n<li>\ud83d\udd2c Conclusion<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  \ud83c\udf9f Introduction <a><\/a>\n<\/h2>\n\n<p>The ERC-721 token standard serves as the foundation for Non-Fungible Tokens (NFTs), providing developers with the capability to design unique digital assets that cannot be duplicated on a blockchain. This feature unlocks the potential for an entirely new realm of experiences, including exclusive access to gated websites or communities restricted to select token holders, as well as innovative games where each item possesses distinct properties such as resealability, multi-functionality, and complete ownership.<\/p>\n\n<p>In the initial segment of this challenge, we will explore the process of implementing an NFT through the utilization of the Vyper programming language.<\/p>\n\n<p>The ability to create and exchange unique digital assets through NFTs has opened up new opportunities for content creators, artists, and collectors to monetize and showcase their work in innovative ways. NFTs have enabled the creation of digital art, music, and collectibles that can be traded bought, and sold as one-of-a-kind assets while providing a secure and transparent record of ownership on the blockchain.<\/p>\n\n<p>Furthermore, the utilization of Vyper programming language in implementing NFTs offers a number of advantages, including higher security, improved gas efficiency, and enhanced readability of the code, which in turn increases the ease of development and maintenance of NFT projects.<\/p>\n\n<h2>\n  \n  \n  \ud83d\udce6 Setup <a><\/a>\n<\/h2>\n\n<p>For setting up the project on a local machine, only one essential component is required: <\/p>\n\n<ul>\n<li><a href=\"https:\/\/www.python.org\/\">Python<\/a><\/li>\n<\/ul>\n\n<p><a href=\"https:\/\/www.python.org\/\">Python<\/a> is the primary programming language used in the project, it includes <a href=\"https:\/\/pypi.org\/project\/pip\/\">PIP<\/a>, which serves as the package manager for Python and <a href=\"https:\/\/docs.python.org\/3\/library\/venv.html\">Virtual ENV<\/a> is an essential tool used for creating a virtual environment that will house the application's code.<\/p>\n\n<p>While the process for setting up these components is beyond the scope of this challenge, in essence, it involves installing Python and configuring a virtual environment for the application's code. It is important to note that creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, thereby improving stability and reproducibility.<\/p>\n\n<h3>\n  \n  \n  Brownie\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/eth-brownie.readthedocs.io\">Brownie<\/a> in this challenge, in your <code>virtual environment<\/code>, <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/install.html\">go ahead and install Brownie, after you installed it<\/a>, create a new folder called <code>nft<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, you might want to use the Hardhat node to test our smart contracts, so inside your project folder, run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install<\/span> <span class=\"nt\">--save-dev<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  ApeWorx\n<\/h3>\n\n<p>If you are going to use <a href=\"https:\/\/docs.apeworx.io\/ape\/stable\/userguides\/quickstart.html#documentation\">ApeWorx<\/a> in this challenge, activate your <code>virtual environment<\/code> and install ApeWorx:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>pip <span class=\"nb\">install <\/span>eth-ape<span class=\"s1\">'[recommended-plugins]'<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After you installed it, create a new folder called <code>nft<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>ape init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  \ud83d\udcd1 Code <a><\/a>\n<\/h2>\n\n<p>The ERC-721 token standard serves as the foundation for Non-Fungible Tokens (NFTs). Inside your <code>contracts<\/code> folder, create a file called <code>nft.vy<\/code> this will contain all of the code necessary to implement the ERC-721.<\/p>\n\n<h3>\n  \n  \n  Non-Fungible Token (ERC-721)\n<\/h3>\n\n<p>Here is a barebones implementation of the <code>ERC721<\/code> token standard in Vyper, can you turn it into a working smart contract?<\/p>\n\n<blockquote>\n<p><strong>Important<\/strong>: \u26a0\ufe0f\ud83d\udc0d If you are new to Vyper, don't worry, it was designed to be simple and readable, making it easier for programmers with any level of experience to quickly grasp the language. If you need more guidance, there are many resources available online to help you get started, such as the Vyper <a href=\"https:\/\/docs.vyperlang.org\/en\/stable\/vyper-by-example.html\">documentation<\/a>, <a href=\"https:\/\/vyper-by-example.org\/\">tutorials<\/a>, and community forums.<br>\n<\/p>\n<\/blockquote>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.7\n<\/span><span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC165<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC721<\/span>\n\n<span class=\"c1\">### INTERFACES ###\n<\/span><span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC721<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC165<\/span>\n\n<span class=\"c1\">### EVENTS ###\n<\/span><span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">approved<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">ApprovalForAll<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">operator<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">approved<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span>\n\n\n<span class=\"c1\">### METHODS ###\n<\/span><span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">view<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">_owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"mi\">0<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">view<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">ownerOf<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">address<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">safeTransferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_data<\/span><span class=\"p\">:<\/span> <span class=\"n\">Bytes<\/span><span class=\"p\">[<\/span><span class=\"mi\">1024<\/span><span class=\"p\">]<\/span><span class=\"o\">=<\/span><span class=\"sa\">b<\/span><span class=\"s\">\"\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">setApprovalForAll<\/span><span class=\"p\">(<\/span><span class=\"n\">_operator<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_approved<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">pass<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">view<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">getApproved<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenId<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">address<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">isApprovedForAll<\/span><span class=\"p\">(<\/span><span class=\"n\">_owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_operator<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># ... TODO: Implementation\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">false<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<blockquote>\n<p>Feel stuck? Take a look at the <a href=\"https:\/\/github.com\/vyperlang\/vyper\/blob\/master\/examples\/tokens\/ERC721.vy\">Vyperlang Official Implemenation<\/a><\/p>\n<\/blockquote>\n\n<h2>\n  \n  \n  \ud83d\udd2c Conclusion <a><\/a>\n<\/h2>\n\n<p>In this challenge, we explored the process of implementing an NFT using the Vyper programming language, which provides developers with a secure and gas-efficient approach to creating unique digital assets that cannot be duplicated on a blockchain. We provided a barebones implementation of the ERC-721 token standard in Vyper and challenged readers to turn it into a working smart contract by implementing the necessary methods and events.<\/p>\n\n<p>Creating and exchanging unique digital assets through NFTs has opened up new opportunities for content creators, artists, and collectors to monetize and showcase their work in innovative ways. NFTs have enabled the creation of digital art, music, and collectibles that can be traded bought, and sold as one-of-a-kind assets while providing a secure and transparent record of ownership on the blockchain.<\/p>\n\n<blockquote>\n<p>\ud83d\udcd2 <strong>Note<\/strong>: Whether using <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/\">Brownie<\/a> or <a href=\"https:\/\/www.apeworx.io\/\">ApeWorx<\/a>, creating a virtual environment for the project ensures that the application's dependencies and requirements are isolated from those of the host system, improving stability and reproducibility.<\/p>\n<\/blockquote>\n\n\n\n<blockquote>\n<p>\ud83d\udc0d <strong>Note<\/strong>: The <a href=\"https:\/\/vyper.readthedocs.io\/\">Vyper programming language<\/a> offers a number of advantages over other languages, including higher security, improved gas efficiency, and enhanced code readability, making it a great option for NFT development projects.<\/p>\n<\/blockquote>\n\n","category":["blockchain","web3","vyper","python"]},{"title":"Understanding Chainlink VRF: A Tool for Random Number Generation on the Blockchain","pubDate":"Mon, 23 Jan 2023 15:55:23 +0000","link":"https:\/\/dev.to\/rabuawad\/understanding-chainlink-vrf-a-tool-for-random-number-generation-on-the-blockchain-a58","guid":"https:\/\/dev.to\/rabuawad\/understanding-chainlink-vrf-a-tool-for-random-number-generation-on-the-blockchain-a58","description":"<p>Random number generation (RNG) is a fundamental building block for many decentralized applications (dApps), from games to smart contracts. However, generating truly random numbers on a blockchain, which is a deterministic system, is a non-trivial task. Chainlink VRF (Verifiable Random Function) is a new tool that aims to solve this problem by providing a secure and verifiable way to generate random numbers on the Ethereum blockchain.<\/p>\n\n<h3>\n  \n  \n  What is Chainlink VRF?\n<\/h3>\n\n<p>Chainlink VRF is a smart contract that implements a verifiable random function (VRF) on the Ethereum blockchain. A VRF is a cryptographic primitive that generates a random value, and also provides proof that the value was generated at random. This is achieved by using a combination of a pseudorandom function (PRF) and a digital signature.<\/p>\n\n<p>The Chainlink VRF smart contract is designed to be used as an oracle, meaning it can be queried by other smart contracts to provide a random value. The smart contract also provides proof of the randomness of the value, which can be verified by any other contract or user.<br>\nHow is it useful?<\/p>\n\n<p>Chainlink VRF is useful for several reasons:<\/p>\n\n<ul>\n<li>\n<strong>True randomness<\/strong>: Chainlink VRF provides a way to generate truly random numbers on the blockchain, which is essential for many dApps that rely on randomness, such as games or lotteries.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li>\n<strong>Verifiability<\/strong>: Chainlink VRF provides proof of the randomness of the generated value, which can be verified by any other contract or user. This ensures that the random value has not been tampered with and was truly generated randomly.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li>\n<strong>Decentralization<\/strong>: Chainlink VRF is a decentralized solution, meaning that it is not controlled by any single entity and is resistant to censorship and tampering. This makes it a more secure and trustless option compared to centralized RNG solutions.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li>\n<strong>Flexibility<\/strong>: Chainlink VRF can be integrated with other smart contracts and dApps, making it a versatile tool for a wide range of use cases.<\/li>\n<\/ul>\n\n<h3>\n  \n  \n  Conclusion\n<\/h3>\n\n<p>Chainlink VRF is a powerful tool for generating truly random numbers on the Ethereum blockchain. It provides a secure, verifiable, and decentralized solution for dApps that rely on randomness, and can be integrated with Solidity and Vyper contracts. As more developers and projects start to adopt this technology, we can expect to see it become a standard building block for many decentralized applications.<\/p>\n\n","category":["music","watercooler"]},{"title":"Understanding Polygon: The L2 Scaling Solution for Ethereum","pubDate":"Thu, 19 Jan 2023 15:45:04 +0000","link":"https:\/\/dev.to\/rabuawad\/understanding-polygon-the-l2-scaling-solution-for-ethereum-3i3p","guid":"https:\/\/dev.to\/rabuawad\/understanding-polygon-the-l2-scaling-solution-for-ethereum-3i3p","description":"<p>As the popularity of decentralized applications (dApps) on the Ethereum network continues to grow, the need for a high-performance, low-cost infrastructure has become increasingly important. This is where <a href=\"https:\/\/polygon.technology\/\">Polygon<\/a> comes in.<\/p>\n\n<p>Polygon (formerly known as Matic Network) is an open-source, multichain scaling solution that aims to provide a high-performance and low-cost infrastructure for decentralized applications (dApps) built on the Ethereum network. It is considered a Layer 2 scaling solution, which means that it runs in parallel to the main Ethereum blockchain, allowing for faster and cheaper transactions.<\/p>\n\n<p>One of the key features of Polygon is its use of a modified version of the Ethereum consensus mechanism called \"Proof of Stake\" with a variant called <a href=\"https:\/\/wiki.polygon.technology\/docs\/home\/blockchain-basics\/sidechain\/\">\"Plasma\" for its side chains.<\/a> This allows for faster and cheaper transactions, while still maintaining the security of the main Ethereum blockchain.<\/p>\n\n<p>Another important feature of Polygon is its concept of \"<a href=\"https:\/\/polygon.technology\/supernets\">Supernets<\/a>.\" Supernets are a collection of interconnected Polygon chains that share a common governance model and token economy. Each Supernet is designed to serve a specific use case or community, and they are designed to be interoperable with each other and with Ethereum.<\/p>\n\n<p>Polygon also provides a suite of other protocols and services, including a decentralized oracle network, a cross-chain communication protocol, and a decentralized governance model. All of these features work together to provide a robust and flexible infrastructure for dApp developers.<\/p>\n\n<p>In terms of deployment, developers can use Polygon's SDKs to easily deploy and interact with their dApps on Polygon's networks, and in order to use Polygon's infrastructure, developers need to pay in $MATIC, the native token of the network, as a transaction fee.<\/p>\n\n<p>Overall, Polygon is a highly promising scaling solution for the Ethereum network. Its use of a modified version of the Ethereum consensus mechanism, its concept of Supernets, and its suite of other protocols and services make it a powerful infrastructure for dApp development.<\/p>\n\n<p>It's worth noting that Polygon also has on its networks a variety of independent projects and protocols that can be used to build decentralized oracle systems, such as Chainlink, API3, others, as well as AMMs, Lending Protocols, and more.<\/p>\n\n","category":["blockchain","web3","polygon","ethereum"]},{"title":"Svelte for Beginners: A Beginner's Guide to Building Web Applications","pubDate":"Wed, 18 Jan 2023 21:48:14 +0000","link":"https:\/\/dev.to\/rabuawad\/svelte-for-beginners-a-beginners-guide-to-building-web-applications-3o5j","guid":"https:\/\/dev.to\/rabuawad\/svelte-for-beginners-a-beginners-guide-to-building-web-applications-3o5j","description":"<p>Svelte is a popular JavaScript framework for building web applications. Thanks to some tricks it is lightweight and easy to use, making it a great option for beginners. In this blog post, we'll take a look at how to set up Svelte and give code samples for working with forms, reactive states, and stores.<\/p>\n\n<h3>\n  \n  \n  Setting up Svelte\n<\/h3>\n\n<p>To get started, you'll need to have <a href=\"https:\/\/nodejs.org\/\" rel=\"noopener noreferrer\">Node.js<\/a> installed on your machine. Once you have Node.js installed, you can use <a href=\"https:\/\/vitejs.dev\/\" rel=\"noopener noreferrer\">Vite<\/a> to create a new Svelte project:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>npm create vite@latest my-svelte-app -- --template svelte\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This will create a new directory called <code>my-svelte-app<\/code> and initialize it with the Svelte template. Next, navigate to the new directory and install the necessary dependencies:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>cd my-svelte-app\nnpm install\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now that you have your project set up, you can start the development server using the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>npm run dev\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This will start a development server and open your project in a web browser. You should see a \"Vite + Svelte\" message on the page, on top of a count button, if you press that button you will see how the count increases, we will learn how to do that ourselves in the following section.<\/p>\n\n<p>Open that directory on a code editor of your choice, you can see an <code>App.svelte<\/code> file inside the <code>src<\/code> folder, remove all of its contents. Also delete the <code>src\/lib<\/code> folder, we will not use it in this case.<\/p>\n\n<h3>\n  \n  \n  Working with Reactive State\n<\/h3>\n\n<p>Svelte uses a reactive system to automatically update the DOM when the state of a component changes. In the following example, we'll create a simple counter that increments and decreases a value when clicking buttons.<\/p>\n\n<p>Open the <code>App.svelte<\/code> file, and type the following:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight html\"><code>\n<span class=\"nt\">&lt;script&gt;<\/span>\n  <span class=\"kd\">let<\/span> <span class=\"nx\">count<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"kd\">function<\/span> <span class=\"nf\">increment<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">count<\/span> <span class=\"o\">+=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"kd\">function<\/span> <span class=\"nf\">decrement<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">count<\/span> <span class=\"o\">-=<\/span> <span class=\"mi\">1<\/span><span class=\"p\">;<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"nt\">&lt;\/script&gt;<\/span>\n\n<span class=\"nt\">&lt;button<\/span> <span class=\"na\">on:click=<\/span><span class=\"s\">{decrement}<\/span><span class=\"nt\">&gt;<\/span>-<span class=\"nt\">&lt;\/button&gt;<\/span>\n<span class=\"nt\">&lt;span&gt;<\/span>{count}<span class=\"nt\">&lt;\/span&gt;<\/span>\n<span class=\"nt\">&lt;button<\/span> <span class=\"na\">on:click=<\/span><span class=\"s\">{increment}<\/span><span class=\"nt\">&gt;<\/span>+<span class=\"nt\">&lt;\/button&gt;<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>In this example, we created two buttons, one to increment the count and one to decrease the count. The <code>on:click<\/code> directive is used to attach click events to the buttons, which call the <code>increment<\/code> and <code>decrement<\/code> functions respectively. The count variable is used to store the current value of the counter, which is displayed in a <code>span<\/code> element using curly braces (<code>{}<\/code>).<\/p>\n\n<p>When the <code>increment<\/code> or <code>decrement<\/code> function is called, the value of the <code>count<\/code> variable is updated, and Svelte's reactive system automatically updates the <code>span<\/code> element to reflect the new value.<\/p>\n\n<h3>\n  \n  \n  Working with forms\n<\/h3>\n\n<p>Svelte makes it easy to work with forms and inputs. In the following example, we'll create a simple form with text input and a submit button. The form will have a <code>submit<\/code> event that will output the text input's value to the console when the button is clicked.<\/p>\n\n<p>Remove all of the contents on <code>App.svelte<\/code>, and write:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight html\"><code>\n<span class=\"nt\">&lt;script&gt;<\/span>\n  <span class=\"kd\">let<\/span> <span class=\"nx\">name<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">\"\"<\/span><span class=\"p\">;<\/span>\n\n  <span class=\"kd\">function<\/span> <span class=\"nf\">handleSubmit<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">console<\/span><span class=\"p\">.<\/span><span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"nx\">name<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">}<\/span>\n<span class=\"nt\">&lt;\/script&gt;<\/span>\n\n<span class=\"nt\">&lt;form<\/span> <span class=\"na\">on:submit<\/span><span class=\"err\">|<\/span><span class=\"na\">preventDefault=<\/span><span class=\"s\">{handleSubmit}<\/span><span class=\"nt\">&gt;<\/span>\n  <span class=\"nt\">&lt;input<\/span> <span class=\"na\">type=<\/span><span class=\"s\">\"text\"<\/span> <span class=\"na\">bind:value=<\/span><span class=\"s\">{name}<\/span><span class=\"nt\">&gt;<\/span>\n  <span class=\"nt\">&lt;button<\/span> <span class=\"na\">type=<\/span><span class=\"s\">\"submit\"<\/span><span class=\"nt\">&gt;<\/span>Submit<span class=\"nt\">&lt;\/button&gt;<\/span>\n<span class=\"nt\">&lt;\/form&gt;<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>In this example, we are using the <code>bind:value<\/code> directive to bind the value of the text input to a variable called name. The <code>on:submit|preventDefault<\/code> directive is used to attach a submit event to the form, which calls the <code>handleSubmit<\/code> function when the button is clicked. The preventDefault modifier is used to prevent the default behavior of the form, which is to refresh the page.<\/p>\n\n<h3>\n  \n  \n  Working with Stores\n<\/h3>\n\n<p>Svelte also allows you to create global stores, which can be used to share states across multiple components. In the following example, we'll create a store for a user's name and age and use it in multiple components.<\/p>\n\n<p>Create a folder inside <code>src<\/code> called <code>stores<\/code>, and inside that folder create a <code>main.js<\/code>, this will be our main store for this application, you can have multiple stores that can do multiple things, but for the sake of simplicity, we will keep this short.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code>\n<span class=\"c1\">\/\/ stores\/main.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">writable<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">svelte\/store<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">name<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">writable<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"\"<\/span><span class=\"p\">);<\/span>\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">age<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">writable<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">);<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that create another folder called <code>components<\/code>, we will create two Svelte files, one called <code>ComponentA.svelte<\/code> and the other will be called <code>ComponentB.svelte<\/code>, you can call the components whatever you like.<\/p>\n\n<p>In the first component, we are going to get the <code>name<\/code> from the store and updated it to something else on that component.<\/p>\n\n<blockquote>\n<p>To subscribe to a store value, you just need to prepend <code>$<\/code> to each variable.<br>\n<\/p>\n<\/blockquote>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight html\"><code>\n<span class=\"c\">&lt;!-- Component A --&gt;<\/span>\n<span class=\"nt\">&lt;script&gt;<\/span>\n    <span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">name<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/stores\/main.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"nt\">&lt;\/script&gt;<\/span>\n\n<span class=\"nt\">&lt;form&gt;<\/span>\n    <span class=\"nt\">&lt;label<\/span> <span class=\"na\">for=<\/span><span class=\"s\">\"name\"<\/span><span class=\"nt\">&gt;<\/span>Name: <span class=\"nt\">&lt;\/label&gt;<\/span>\n    <span class=\"nt\">&lt;input<\/span> <span class=\"na\">id=<\/span><span class=\"s\">\"name\"<\/span> <span class=\"na\">type=<\/span><span class=\"s\">\"text\"<\/span> <span class=\"na\">bind:value=<\/span><span class=\"s\">{$name}<\/span><span class=\"nt\">&gt;<\/span>\n<span class=\"nt\">&lt;\/form&gt;<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now in the second component, we are going to get the <code>age<\/code> from the store and updated it to something else on that component.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight html\"><code>\n<span class=\"c\">&lt;!-- Component B --&gt;<\/span>\n<span class=\"nt\">&lt;script&gt;<\/span>\n    <span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">age<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/stores\/main.js<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"nt\">&lt;\/script&gt;<\/span>\n\n<span class=\"nt\">&lt;form&gt;<\/span>\n    <span class=\"nt\">&lt;label<\/span> <span class=\"na\">for=<\/span><span class=\"s\">\"age\"<\/span><span class=\"nt\">&gt;<\/span>Age: <span class=\"nt\">&lt;\/label&gt;<\/span>\n    <span class=\"nt\">&lt;input<\/span> <span class=\"na\">id=<\/span><span class=\"s\">\"age\"<\/span> <span class=\"na\">type=<\/span><span class=\"s\">\"number\"<\/span> <span class=\"na\">bind:value=<\/span><span class=\"s\">{$age}<\/span><span class=\"nt\">&gt;<\/span>\n<span class=\"nt\">&lt;\/form&gt;<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that, we can go back to our <code>App.svelte<\/code> file, remove all of its contents and import the two components:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight html\"><code>\n<span class=\"nt\">&lt;script&gt;<\/span>\n  <span class=\"k\">import<\/span> <span class=\"nx\">ComponentA<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/components\/ComponentA.svelte<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">import<\/span> <span class=\"nx\">ComponentB<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/components\/ComponentB.svelte<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"nx\">age<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">.\/stores\/main.js<\/span><span class=\"dl\">\"<\/span>\n<span class=\"nt\">&lt;\/script&gt;<\/span>\n\n<span class=\"nt\">&lt;ComponentA<\/span> <span class=\"nt\">\/&gt;<\/span>\n<span class=\"nt\">&lt;ComponentB<\/span> <span class=\"nt\">\/&gt;<\/span>\n\n<span class=\"nt\">&lt;h1&gt;<\/span>Hello I'm {$name}, and I'm {$age} years old<span class=\"nt\">&lt;\/h1&gt;<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>In this example, we have created two stores for a user's name and age in the <code>stores\/main.js<\/code> file. We then import and use these stores in two different components. We use the <code>bind:value<\/code> directive to bind the input value to the store. As you can see, the value of the store is reactive and will change if the input is changed.<\/p>\n\n<p>In summary, Svelte is a powerful and easy-to-use JavaScript framework for building web applications. It allows you to work with forms, reactive states, and stores in a simple and intuitive way. This guide should give you a good starting point for building your own Svelte applications.<\/p>\n\n","category":["discuss","deployment","productivity","culture"]},{"title":"Create a blockchain asset tracking system using an ERC-721-inspired smart contract!","pubDate":"Thu, 12 Jan 2023 17:26:09 +0000","link":"https:\/\/dev.to\/rabuawad\/create-a-blockchain-asset-tracking-system-using-an-erc-721-inspired-smart-contract-3j5a","guid":"https:\/\/dev.to\/rabuawad\/create-a-blockchain-asset-tracking-system-using-an-erc-721-inspired-smart-contract-3j5a","description":"<h2>\n  \n  \n  Introduction\n<\/h2>\n\n<p>Most asset tracking done today is done using something as basic and as insecure as a simple spreadsheet, in some cases a most sophisticated approach is done with some kind of database with custom software as an interface.<\/p>\n\n<p>Both are extremely insecure and can be altered by an attacker. Let us imagine a company that distributes high-end computer boards, not only sells them but leases them to different types of organizations for testing, marketing, and more. If an attacker wanted to modify this register using the current approach it would be as simple as accessing the database or spreadsheet and changing a simple record.<\/p>\n\n<p>Using multi-ownable smart contracts would prevent this kind of behavior by default, and asset tracking with NFTs can give better control of where is each asset and with some extra code give a lot more information than what can be stored in a simple spreadsheet.<\/p>\n\n<h2>\n  \n  \n  Solving this problem\n<\/h2>\n\n<p>This problem can be solved using blockchain technology:<\/p>\n\n<ol>\n<li>Create smart contracts that enable the company to track its assets transparently and reliably.<\/li>\n<li>Create a custom blockchain to solve this issue.<\/li>\n<\/ol>\n\n<p>in this article, we are going to see the first approach, but the second one can be as, if not more interesting and reliable.<\/p>\n\n<h2>\n  \n  \n  Smart-contracts\n<\/h2>\n\n<p>For this approach, we only need one smart contract for tracking the assets.<\/p>\n\n<p>We are going to use a similar approach to the ERC-721 token standard, but with a lot of parts removed and a lot of modifications.<\/p>\n\n<p>Since we don't want users to trade tokens like a normal NFT, we also what the ability to remove token access to a given access, and we want to control who can have what.<\/p>\n\n<h2>\n  \n  \n  Interfaces\n<\/h2>\n\n<p>This interface defines the asset collection itself and is a stripped-down version of an ERC-721.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>\/\/ SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IAssetCollection {\n    event Transfer(\n        address indexed from,\n        address indexed to,\n        uint256 indexed tokenId\n    );\n\n    function name() external view returns (string memory);\n\n    function balanceOf(address owner) external view returns (uint256);\n\n    function tokensOf(address tokenHolder)\n        external\n        view\n        returns (uint256[] memory);\n\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n\n    function mint(address tokenHolder, string memory tokenURI) external;\n\n    function burn(address tokenHolder, uint256 tokenId) external;\n\n    function transfer(uint256 tokenId) external;\n\n    function transferFrom(\n        address tokenHolder,\n        address to,\n        uint256 tokenId\n    ) external;\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This interface describes is to allow control over the smart contract.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>\/\/ SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\ninterface IOwnable {\n    event TransferOwnership(address indexed from, address indexed to);\n\n    function owner() external view returns (address);\n\n    function transferOwnership(address _newOwner) external;\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Smart-contract\n<\/h2>\n\n<p>The main smart contract is the Asset Collection smart contract, this contract is responsible for managing all the assets inside a particular collection, we (as the owners of the smart contract) can mint, burn, move and transfer tokens, each token represents an asset.<\/p>\n\n<p>We <em>don't<\/em> want users to trade tokens (like NFTs), but we need the basic functionality from an ERC-721. <\/p>\n\n<p>Due to limitations on smart contract data storage, we are storing all the relevant information outside the blockchain, preferably on a persistent storage platform (like <a href=\"https:\/\/medium.com\/nearprotocol\/introducing-machina-the-worlds-first-proof-of-stake-storage-solution-built-on-near-fed2ed23dbfb\" rel=\"noopener noreferrer\">Machina<\/a> or <a href=\"https:\/\/www.arweave.org\/\" rel=\"noopener noreferrer\">Arweave<\/a>), and using the token URI metadata pattern used commonly for NFTs.<\/p>\n\n<p>Based on our work on the interface defined above, we will overview some functions.<\/p>\n\n<p><strong>Mint<\/strong><br>\nThe \"mint\" function can only be called ourselves (the owner) and is similar to the mint function found on any other NFT smart contracts. It gives us the ability to create a token.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>function mint(address tokenHolder, string memory _tokenURI)\n    public\n    onlyOwner\n{\n    uint256 tokenId = _tokenIds;\n    _tokenIds += 1;\n    _setTokenURI(tokenId, _tokenURI);\n    _mint(tokenHolder, tokenId);\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><strong>Burn<\/strong><br>\nThe \"burn\" method allows us to destroy a token permanently.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>function burn(address tokenHolder, uint256 tokenId)\n    public\n    onlyOwner\n{\n    _mint(tokenHolder, tokenId);\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><strong>Transfer<\/strong><br>\nThe \"transfer\" method returns a token back to us, and can only be called by the token owner itself.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>function transfer(uint256 tokenId) public {\n    _transfer(msg.sender, _owner, tokenId);\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p><strong>Transfer from<\/strong><br>\nThe \"transfer from\" method allows us (the owner) to control tokens on behalf of a user. If we want to change the holder or if we need to take it back and assign it to ourselves again.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>\/\/ Moves a token from one user to another\nfunction transferFrom(\n    address tokenHolder,\n    address to,\n    uint256 tokenId\n) public onlyOwner {\n    _transfer(tokenHolder, to, tokenId);\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The final smart contract should look something like this.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>\/\/ SPDX-License-Identifier: MIT\npragma solidity ^0.8.13;\n\nimport \".\/interfaces\/IAssetCollection.sol\";\nimport \".\/interfaces\/IOwnable.sol\";\n\ncontract AssetCollection is IAssetCollection, IOwnable {\n    \/\/ Token ID counter\n    uint256 private _tokenIds;\n\n    \/\/ Owner of the smart-contract\n    address private _owner;\n\n    \/\/ Name of the asset collection\n    string private _name;\n\n    \/\/ Mapping from token ID to owner address\n    mapping(uint256 =&gt; address) private _owners;\n\n    \/\/ Mapping owner address to token count\n    mapping(address =&gt; uint256) private _balances;\n\n    \/\/ Mapping from token ID to token URI\n    mapping(uint256 =&gt; string) private _tokenURIs;\n\n    constructor(string memory __name) {\n        _name = __name;\n        _owner = msg.sender;\n    }\n\n    modifier onlyOwner() {\n        require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    function _exists(uint256 tokenId) internal view returns (bool) {\n        return _owners[tokenId] != address(0);\n    }\n\n    function _setTokenURI(uint tokenId, string memory _tokenURI) internal {\n        _tokenURIs[tokenId] = _tokenURI;\n    }\n\n    function _mint(address to, uint256 tokenId) internal {\n        require(to != address(0), \"ERC721: mint to the zero address\");\n        \/\/ Check that tokenId was not minted\n        require(!_exists(tokenId), \"ERC721: token already minted\");\n\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal {\n        require(\n            ownerOf(tokenId) == from,\n            \"ERC721: transfer from incorrect owner\"\n        );\n        require(to != address(0), \"ERC721: transfer to the zero address\");\n\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n    }\n\n    function _burn(uint256 tokenId) internal {\n        address tokenOwner = ownerOf(tokenId);\n        _balances[tokenOwner] -= 1;\n\n        emit Transfer(tokenOwner, address(0), tokenId);\n    }\n\n    \/\/ Creates token\n    function mint(address tokenHolder, string memory _tokenURI)\n        public\n        onlyOwner\n    {\n        uint256 tokenId = _tokenIds;\n        _tokenIds += 1;\n        _setTokenURI(tokenId, _tokenURI);\n        _mint(tokenHolder, tokenId);\n    }\n\n    \/\/ Destroys token\n    function burn(address tokenHolder, uint256 tokenId) public onlyOwner {\n        _mint(tokenHolder, tokenId);\n    }\n\n    \/\/ Transfer the token back to the DAO\n    function transfer(uint256 tokenId) public {\n        _transfer(msg.sender, _owner, tokenId);\n    }\n\n    \/\/ Moves a token from one user to another\n    function transferFrom(\n        address tokenHolder,\n        address to,\n        uint256 tokenId\n    ) public onlyOwner {\n        _transfer(tokenHolder, to, tokenId);\n    }\n\n    \/\/ Returns how many tokens a user owns\n    function balanceOf(address tokenOwner) public view returns (uint256) {\n        require(\n            tokenOwner != address(0),\n            \"ERC721: address zero is not a valid owner\"\n        );\n        return _balances[tokenOwner];\n    }\n\n    \/\/ Returns how many tokens a user owns\n    function tokensOf(address tokenOwner)\n        public\n        view\n        returns (uint256[] memory)\n    {\n        require(\n            tokenOwner != address(0),\n            \"ERC721: address zero is not a valid owner\"\n        );\n\n        uint256 balance = balanceOf(tokenOwner);\n        uint256[] memory tokens = new uint[](balance);\n        uint256 index = 0;\n\n        for (uint id = 0; id &lt; _tokenIds; id++) {\n            if (_owners[id] == tokenOwner) {\n                tokens[index] = id;\n                index += 1;\n            }\n        }\n\n        return tokens;\n    }\n\n    \/\/ Returns the token URI of the token\n    function tokenURI(uint256 tokenId) public view returns (string memory) {\n        require(_exists(tokenId), \"ERC721: token hasn't been minted\");\n        return _tokenURIs[_tokenIds];\n    }\n\n    \/\/ Returns the owner of the token\n    function ownerOf(uint256 tokenId) public view returns (address) {\n        address tokenOwner = _owners[tokenId];\n        require(tokenOwner != address(0), \"ERC721: invalid token ID\");\n        return tokenOwner;\n    }\n\n    \/\/ Transfers the ownership of the smart-contract\n    function transferOwnership(address _newOwner) public {\n        require(msg.sender == _owner, \"Ownable: Caller is not owner\");\n        require(\n            _newOwner == address(0),\n            \"Ownable: New owner can not be the zero address\"\n        );\n\n        address olOwner = _owner;\n        _owner = _newOwner;\n        emit TransferOwnership(olOwner, _newOwner);\n    }\n\n    \/\/ Returns name of the collection\n    function name() public view returns (string memory) {\n        return _name;\n    }\n\n    \/\/ Returns owner of the smart-contract\n    function owner() public view returns (address) {\n        return _owner;\n    }\n}\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This token allows us to track an asset securely and transparently.<\/p>\n\n<p>This is only contract is just for demonstration purposes and is not optimized nor audited.<\/p>\n\n<p><a href=\"https:\/\/testnet.snowtrace.io\/address\/0xDd839965671b24D99B6c92d553E269a99bccEcdB#readContract\" rel=\"noopener noreferrer\">Asset Collection smart contract deployed on the Avalanche Testnet<\/a><\/p>\n\n","category":["aws","mcp","programming"]},{"title":"Create an Automated Market Maker (AMM) with Vyper! \ud83d\udc0d","pubDate":"Wed, 11 Jan 2023 21:46:19 +0000","link":"https:\/\/dev.to\/rabuawad\/create-an-automated-market-maker-amm-on-avalanche-with-vyper-hke","guid":"https:\/\/dev.to\/rabuawad\/create-an-automated-market-maker-amm-on-avalanche-with-vyper-hke","description":"<h2>\n  \n  \n  Introduction\n<\/h2>\n\n<p>Welcome, in this tutorial, we will learn how to build an AMM with features like adding liquidity, removing liquidity &amp; swapping tokens with shares and fees. The first smart contract can take in any two ERC20 tokens and make a liquidity pool with those, and the second one is used to deploy liquidity pools. We are going to use <a href=\"https:\/\/vyper.readthedocs.io\/en\/stable\/\">vyper<\/a> to write the entirety of the smart contacts.<\/p>\n\n<h2>\n  \n  \n  Prerequisites\n<\/h2>\n\n<ul>\n<li>Basic programming and console\/terminal use experience<\/li>\n<li>A simple understanding of Solidity or Vyper<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  Requirements\n<\/h2>\n\n<ul>\n<li><a href=\"https:\/\/nodejs.org\/en\/\">NodeJS<\/a><\/li>\n<li>\n<a href=\"https:\/\/www.python.org\/\">Python<\/a> and <a href=\"https:\/\/eth-brownie.readthedocs.io\/\">Brownie ETH<\/a>, or any smart contract framework<\/li>\n<li>\n<a href=\"https:\/\/code.visualstudio.com\/\">VSCode<\/a>, or another code editor<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  What is an AMM?\n<\/h2>\n\n<p>Automated market makers (AMMs) are part of the decentralized finance (Defi) ecosystem. They allow digital assets to be traded in a permissionless and automatic way by using liquidity pools rather than a traditional market of buyers and sellers. AMM users supply liquidity pools with crypto tokens, whose prices are determined by a constant mathematical formula. Liquidity pools can be optimized for different purposes, and are proving to be an important instrument in the Defi ecosystem. In this tutorial, we are going to use a constant-product AMM.<\/p>\n\n<h2>\n  \n  \n  Setup\n<\/h2>\n\n<p>We are going to use <a href=\"https:\/\/eth-brownie.readthedocs.io\">Brownie<\/a> in this tutorial, <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/install.html\">after you installed Brownie<\/a>, create a new folder called <code>avalanche-swap<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, we are going to be using the Hardhat node to test our smart contracts, so inside your project folder, run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install<\/span> <span class=\"nt\">--save-dev<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Implementing the <strong>pair<\/strong> smart-contract\n<\/h2>\n\n<p>Let's start with the boilerplate code. We create a file named <code>contracts\/AvaSwapPair.vy<\/code>, define the vyper version as &gt;= 0.3.7, and import the ERC20 and ERC20 Detailed interfaces from vyper.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version ^0.3.7\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This is our basic boilerplate, we need the ERC20 definition to allow our users to use their shares however they want.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version ^0.3.7\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"c1\">###### EVENTS ######\n<\/span>\n<span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"c1\">###### STATE ######\n<\/span>\n<span class=\"c1\"># Share's token name\n<\/span><span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># Share's token symbol\n<\/span><span class=\"n\">symbol<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># Share's token decimals\n<\/span><span class=\"n\">decimals<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint8<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># By declaring `balanceOf` as public, vyper automatically generates a 'balanceOf()' getter\n# method to allow access to account balances.\n<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># By declaring `allowance` as public, vyper automatically generates the `allowance()` getter\n<\/span><span class=\"n\">allowance<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># By declaring `totalSupply` as public, we automatically create the `totalSupply()` getter\n<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\">###### CONSTRUCTOR ######\n<\/span><span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">():<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"Avalanche Swap\"<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">symbol<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"AVAS\"<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">decimals<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">18<\/span>\n\n\n<span class=\"c1\">###### INTERNAL METHODS ######\n<\/span><span class=\"o\">@<\/span><span class=\"n\">internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"s\">\"ERC20: mint to the zero address\"<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"s\">\"ERC20: burn to the zero address\"<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"s\">\"ERC20: transfer to the zero address\"<\/span>\n\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">][<\/span><span class=\"n\">_spender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This is a basic ERC20 smart contract, we are going to need this basic functionality to implement a proper AMM. Our users will receive <code>shares<\/code> each time they deposit liquidity, each share is an ERC20 token. And can redeem these shares for the tokens that they deposited with an extra tip for doing so.<\/p>\n\n<p>The smart contract is divided on:<\/p>\n\n<ul>\n<li><strong>EVENTS<\/strong><\/li>\n<li><strong>STATE<\/strong><\/li>\n<li><strong>INTERNAL METHODS<\/strong><\/li>\n<li><strong>EXTERNAL METHODS<\/strong><\/li>\n<\/ul>\n\n<blockquote>\n<p>This part is important since we are going to jump between those. So take note so you don't get lost.<\/p>\n<\/blockquote>\n\n<p>We would be set on the ERC20 functionality of our smart contract to manage the pool shares we are going to distribute to our liquidity providers, this part is really common so we are not going to go into detail. <a href=\"https:\/\/dev.to\/rafael_abuawad\/create-a-wrapped-erc20-token-on-avalanche-with-vyper-1827\">Check out this blog post that I made on how to create a wrapped token using a similar approach, here I explain how ERC20 tokens work, why they are important, and how we can create a custom one linked to a cryptocurrency.<\/a><\/p>\n\n<p>After that is done we need to add a few state variables to our smart contract to add the AMM functionality. Let's start with the tokens and the reserves:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"c1\"># Pair tokens\n<\/span><span class=\"n\">token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># Reserve records\n<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">reserve1<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The token variables will keep track of which tokens the pool handles and the reserves will keep track of the amount that we have for each token.<\/p>\n\n<p>Now we also need an internal update method to update the reserves each time we add or remove liquidity.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### INTERNAL METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">_reserve0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_reserve1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve0<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve1<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Finally, we need to add a setup function and set up a state variable flag that is going to be called by that factory, this function will set the tokens and with the flag, it can only be called once.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"c1\"># Setup flag\n<\/span><span class=\"n\">_setup<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Since the method will be called from the outside we need to define it in the external methods section.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_setup<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">False<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Pair: already initialized\"<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token0<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token1<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_setup<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">True<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Add liquidity\n<\/h3>\n\n<p>Adding liquidity allows our AMM to work, without liquidity, there would not be any swapping of tokens. The <em>addLiquidity<\/em> method is really simple, the user deposits some tokens to our smart contract (the initial k=x*y is defined by the first deposit) in return the smart contract mints some share tokens to redeem these tokens later, with some collected fees as a result of other users swapping tokens with this liquidity.<\/p>\n\n<p>We added a reentrancy guard to prevent bad actors from exploiting this functionality.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"s\">\"add\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"c1\"># add liquidity\n<\/span>    <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"n\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"bp\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"n\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"bp\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># keep the pool balanced (k=x*y)\n<\/span>    <span class=\"k\">if<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">or<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">assert<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Pair: x \/ y != dx \/ dy\"<\/span> \n\n    <span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">if<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"n\">isqrt<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">min<\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount1<\/span> <span class=\"o\">*<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n        <span class=\"p\">)<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">shares<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Pair: shares were zero\"<\/span>\n\n    <span class=\"c1\"># mint shares to liquidity provider\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">shares<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">),<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">shares<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Remove liquidity\n<\/h3>\n\n<p>Removing the liquidity is straightforward, we burn the shares that the user passes in and we transfer the corresponding tokens to that user.<\/p>\n\n<p>We added a reentrancy guard to prevent bad actors from exploiting this functionality.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"s\">\"remove\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">bal0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token0<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">bal1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal0<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n    <span class=\"n\">amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal1<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n\n    <span class=\"c1\"># _burn checks if the user has enough shares\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_shares<\/span><span class=\"p\">)<\/span>\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">bal0<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">bal1<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># transfers the tokens back\n<\/span>    <span class=\"n\">_token0<\/span><span class=\"p\">.<\/span><span class=\"n\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">_token1<\/span><span class=\"p\">.<\/span><span class=\"n\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"p\">(<\/span><span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Swap\n<\/h3>\n\n<p>The swap functionality is essential on any AMM, here a user passes a token and an amount, and with these two we return the opposite token of the pair with the corresponding amount, taking a small fee for our liquidity providers in the process.<\/p>\n\n<p>We added a reentrancy guard to prevent bad actors from exploiting this functionality.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### EXTERNAL METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"o\">@<\/span><span class=\"n\">nonreentrant<\/span><span class=\"p\">(<\/span><span class=\"s\">\"swap\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"ow\">or<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Pair: invalid token\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_amountIn<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Pair: amount in is zero\"<\/span>\n\n    <span class=\"c1\"># variables to interact with the liquidity pool\n<\/span>    <span class=\"n\">tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">reserveIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"n\">reserveOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n    <span class=\"c1\"># determine which token is being swapped in\n<\/span>    <span class=\"c1\"># and assigning variables accordingly\n<\/span>    <span class=\"n\">isToken0<\/span><span class=\"p\">:<\/span> <span class=\"nb\">bool<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">isToken0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n\n    <span class=\"c1\"># transfer in the tokens\n<\/span>    <span class=\"n\">tokenIn<\/span><span class=\"p\">.<\/span><span class=\"n\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"bp\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># 0.3% fee\n<\/span>    <span class=\"n\">amountInWithFee<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_amountIn<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">997<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">1000<\/span>\n\n    <span class=\"c1\"># calculate tokens to transfer\n<\/span>    <span class=\"n\">amountOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveOut<\/span> <span class=\"o\">*<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveIn<\/span> <span class=\"o\">+<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">.<\/span><span class=\"n\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amountOut<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># update reserves\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">),<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"c1\"># transfer in the tokens\n<\/span>    <span class=\"k\">return<\/span> <span class=\"n\">amountOut<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Implementing the <strong>factory<\/strong> smart-contract\n<\/h2>\n\n<p>Let's start with the boilerplate code. We create a file named <code>contracts\/AvaSwapFactory.vy<\/code>, and define the vyper version as 0.3.7. This smart contract is responsible for creating liquidity pools, using two tokens that the user can pass in.<\/p>\n\n<p>Your smart contract should be looking something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version ^0.3.7\n<\/span>\n<span class=\"c1\">###### INTERFACES ######\n<\/span>\n<span class=\"c1\">###### STATE ######\n<\/span>\n<span class=\"c1\">###### CONSTRUCTOR ######\n<\/span>\n<span class=\"c1\">###### METHODS ######\n<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This is empty for now.<\/p>\n\n<p>First, we are going to define an interface of the pair smart contract that we built previously, the interface itself only needs one method declared, the setup method, since that is what we are going to use to define a pair.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"p\">...<\/span>\n<span class=\"c1\">###### INTERFACES ######\n<\/span>\n<span class=\"n\">interface<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">def<\/span> <span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span> <span class=\"n\">nonpayable<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that we are going to declare the state of the smart contract, we need to map the token pairs that we have created, and we need to add an array to store each one of them, also a master pair contract address, this is going to be used as a blueprint by vyper to create and deploy new pair smart contracts.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### STATE ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"c1\"># Pair Contract =&gt; Token &lt;=&gt; Token\n<\/span><span class=\"n\">getPair<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">address<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># All pairs list\n<\/span><span class=\"n\">allPairs<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">DynArray<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"mi\">30<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># AvaSwap Pair contract address used to create clones of it\n<\/span><span class=\"n\">pairContract<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that we are going to define the constructor, this part is really important since here is where we pass the address to an empty pair smart contract that we need to deploy before we deploy this one.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### CONSTRUCTOR ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">(<\/span><span class=\"n\">_pairContract<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">pairContract<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_pairContract<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that would be everything we need before defining the main <em>createPair<\/em> method, which will allow our users to create a token pair freely.<\/p>\n\n<h3>\n  \n  \n  Create pair\n<\/h3>\n\n<p>The create pair method is simple, we pass in two tokens, token A and token B, with these two tokens we deploy a new pair smart contract (using the <em>pairContract<\/em> state variable we defined in the constructor) and we added to the pairs mapping and the pairs array, and that's it!<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">###### METHODS ######\n<\/span><span class=\"p\">...<\/span>\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">address<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenA<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"Avalanche Swap Factory: identical addresses\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenA<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">_tokenB<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"s\">\"Avalanche Swap Factory: zero address\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">]<\/span> <span class=\"o\">==<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span>  <span class=\"s\">\"Avalanche Swap Factory: pair exists\"<\/span>\n\n    <span class=\"c1\"># create pair smart contract\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">create_forwarder_to<\/span><span class=\"p\">(<\/span><span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">pairContract<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">).<\/span><span class=\"n\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">,<\/span> <span class=\"n\">_tokenB<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># populate mapping in, and in the reverse direction\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">getPair<\/span><span class=\"p\">[<\/span><span class=\"n\">_tokenB<\/span><span class=\"p\">][<\/span><span class=\"n\">_tokenA<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span>\n\n    <span class=\"c1\"># append pair to all pairs array\n<\/span>    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allPairs<\/span><span class=\"p\">.<\/span><span class=\"n\">append<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">pair<\/span>\n\n<span class=\"p\">...<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Testing using <a href=\"https:\/\/eth-brownie.readthedocs.io\/\">Brownie<\/a>\n<\/h2>\n\n<p>In this tutorial, we are going to use Brownie to test our smart contracts, you can use any other smart contract framework if you are familiar with it <a href=\"https:\/\/hardhat.org\/\">Hardhat<\/a> or <a href=\"https:\/\/academy.apeworx.io\/\">ApeWorx<\/a> both have support for developing and deploying vyper smart contracts.<\/p>\n\n<p>For this, we are going to create an extra mock ERC20 smart contract, that we are going to use to deploy mocks tokens to test our application.<\/p>\n\n<p>Create a <code>mock<\/code> directory inside our <code>contracts<\/code> folder, and then create an <code>ERC20.vy<\/code> smart contract inside it.<\/p>\n\n<p>The contents of that smart contract should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version ^0.3.7\n# @dev Implementation of ERC-20 token standard.\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"nn\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"n\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n<span class=\"n\">symbol<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n<span class=\"n\">decimals<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint8<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"n\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">minter<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">(<\/span><span class=\"n\">_name<\/span><span class=\"p\">:<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">],<\/span> <span class=\"n\">_symbol<\/span><span class=\"p\">:<\/span> <span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">],<\/span> <span class=\"n\">_decimals<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint8<\/span><span class=\"p\">,<\/span> <span class=\"n\">_supply<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">init_supply<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_supply<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">10<\/span> <span class=\"o\">**<\/span> <span class=\"n\">convert<\/span><span class=\"p\">(<\/span><span class=\"n\">_decimals<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_name<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">symbol<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_symbol<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">decimals<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_decimals<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">init_supply<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">=<\/span> <span class=\"n\">init_supply<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">minter<\/span> <span class=\"o\">=<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">init_supply<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">][<\/span><span class=\"n\">_spender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span> <span class=\"o\">==<\/span> <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">minter<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burnFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"bp\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that go to our <code>tests<\/code> folder and create a <code>conftest.py<\/code> here we will define all of our fixtures (fixtures act like functions that return a new deployment each time) to test our application. We only need 2 demo tokens to test our AMM.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\">#!\/usr\/bin\/python3\n<\/span>\n<span class=\"kn\">import<\/span> <span class=\"nn\">pytest<\/span>\n\n\n<span class=\"c1\"># Demo token for testing purposes only\n<\/span><span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"s\">\"function\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_token<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Test Token\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"TST\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">18<\/span><span class=\"p\">,<\/span> <span class=\"mf\">1e21<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n\n<span class=\"c1\"># Demo token for testing purposes only\n<\/span><span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"s\">\"function\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">demo_token<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">ERC20<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">(<\/span><span class=\"s\">\"Demo Token\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"DEMO\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">18<\/span><span class=\"p\">,<\/span> <span class=\"mf\">1e21<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"s\">\"function\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">ava_swap_pair<\/span><span class=\"p\">(<\/span><span class=\"n\">AvaSwapPair<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">({<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"s\">\"function\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">ava_swap_factory<\/span><span class=\"p\">(<\/span><span class=\"n\">AvaSwapFactory<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">ava_swap_pair<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">return<\/span> <span class=\"n\">AvaSwapFactory<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">ava_swap_factory<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that is setup we can test the main functionality of our AMM, mainly:<\/p>\n\n<ul>\n<li>Create a liquidity pool (pair)<\/li>\n<li>Add liquidity<\/li>\n<li>Remove liquidity<\/li>\n<li>Swap and collect fees using shares<\/li>\n<\/ul>\n\n<p>Now create a file inside our <code>tests<\/code> folder, called <code>test_amm.py<\/code>, this will test all the functionality that we defined earlier.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">import<\/span> <span class=\"nn\">brownie<\/span> \n<span class=\"kn\">from<\/span> <span class=\"nn\">brownie<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">,<\/span> <span class=\"n\">Wei<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Your file should be looking like that before we begin writing tests. Here we import the AvaSwapPair contract container to interact with the pairs that we create and Wei to manipulate token amounts easily.<\/p>\n\n<h3>\n  \n  \n  Create a liquidity pool\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"k\">def<\/span> <span class=\"nf\">test_create_pair<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># create pair\n<\/span>    <span class=\"n\">tx_create_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">.<\/span><span class=\"n\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span> \n    <span class=\"c1\"># we access the created pair address\n<\/span>    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tx_create_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">return_value<\/span>\n    <span class=\"c1\"># we access the pair smart-contract\n<\/span>    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># test default pair values\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Add liquidity\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"k\">def<\/span> <span class=\"nf\">test_add_liquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># create pair\n<\/span>    <span class=\"n\">tx_create_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">.<\/span><span class=\"n\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span> \n    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tx_create_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">return_value<\/span>\n    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">\"1000 ether\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># approve pair to use our tokens\n<\/span>    <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># add liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span> <span class=\"c1\"># minted shares\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Remove liquidity\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"k\">def<\/span> <span class=\"nf\">test_remove_liquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># create pair\n<\/span>    <span class=\"n\">tx_create_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">.<\/span><span class=\"n\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span> \n    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tx_create_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">return_value<\/span>\n    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">\"1000 ether\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># approve pair to use our tokens\n<\/span>    <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># add liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span> <span class=\"c1\"># minted shares\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">amount<\/span>\n\n    <span class=\"c1\"># get shares\n<\/span>    <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># remove liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span> <span class=\"c1\"># minted shares\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Swap and collect fees using shares\n<\/h3>\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"k\">def<\/span> <span class=\"nf\">test_remove_liquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">,<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">):<\/span>\n    <span class=\"c1\"># create pair\n<\/span>    <span class=\"n\">tx_create_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">ava_swap_factory<\/span><span class=\"p\">.<\/span><span class=\"n\">createPair<\/span><span class=\"p\">(<\/span><span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span> \n    <span class=\"n\">pair_address<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tx_create_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">return_value<\/span>\n    <span class=\"n\">pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">at<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">\"1000 ether\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">swap_amount<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">\"100 ether\"<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># approve pair to use our tokens\n<\/span>    <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># add liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># initial balance before swap\n<\/span>    <span class=\"n\">initial_balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"s\">\"test_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"s\">\"demo_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># approve token in\n<\/span>    <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">pair_address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"c1\"># swap\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">swap_amount<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"n\">balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"s\">\"test_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"s\">\"demo_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># test that we swapped tokens correctly\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"demo_token\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"demo_token\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"test_token\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">&gt;<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"test_token\"<\/span><span class=\"p\">]<\/span>\n\n    <span class=\"c1\"># get shares\n<\/span>    <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"c1\"># remove liquidity\n<\/span>    <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">shares<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span> <span class=\"c1\"># minted shares\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">pair<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">pair<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span>\n\n    <span class=\"n\">balances<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n        <span class=\"s\">\"test_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">test_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]),<\/span>\n        <span class=\"s\">\"demo_token\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">demo_token<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\"># test that we swapped tokens correctly\n<\/span>    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"demo_token\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"demo_token\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"test_token\"<\/span><span class=\"p\">]<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">balances<\/span><span class=\"p\">[<\/span><span class=\"s\">\"test_token\"<\/span><span class=\"p\">]<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To run our tests, on your terminal run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie <span class=\"nb\">test<\/span> <span class=\"nt\">--network<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This will test our smart contracts on the hardhat local node.<\/p>\n\n<p>That would be it, we can extend our testing to include every possible scenario, but we will not cover that in this tutorial.<\/p>\n\n<h2>\n  \n  \n  Deploy using <a href=\"https:\/\/eth-brownie.readthedocs.io\/\">Brownie<\/a>\n<\/h2>\n\n<p>In this tutorial, we are going to use Brownie to deploy our smart contracts, you can use any other smart contract framework if you are familiar with it <a href=\"https:\/\/hardhat.org\/\">Hardhat<\/a> or <a href=\"https:\/\/academy.apeworx.io\/\">ApeWorx<\/a> both have support for developing and deploying vyper smart contracts.<\/p>\n\n<p>Since we are deploying to Avalanche, we need to add the Avalanche mainnet and the Avalanche Fuji testnet to our supported networks. In our terminal type the following:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie networks add Avalanche avax-testnet <span class=\"nv\">host<\/span><span class=\"o\">=<\/span>https:\/\/api.avax-test.network\/ext\/bc\/C\/rpc <span class=\"nv\">chainid<\/span><span class=\"o\">=<\/span>43113 <span class=\"nv\">explorer<\/span><span class=\"o\">=<\/span>https:\/\/testnet.snowtrace.io\/ <span class=\"nv\">name<\/span><span class=\"o\">=<\/span>Fuji\n<\/code><\/pre>\n\n<\/div>\n\n\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie networks add Avalanche avax-mainnet <span class=\"nv\">host<\/span><span class=\"o\">=<\/span>https:\/\/api.avax.network\/ext\/bc\/C\/rpc <span class=\"nv\">chainid<\/span><span class=\"o\">=<\/span>43114 <span class=\"nv\">explorer<\/span><span class=\"o\">=<\/span>https:\/\/snowtrace.io\/ <span class=\"nv\">name<\/span><span class=\"o\">=<\/span>Mainnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After we run these two commands brownie will add Avalanche to Brownie.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>Avalanche\n  \u251c\u2500Mainnet: avax-mainnet\n  \u2514\u2500Fuji: avax-testnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that is complete, you can write our deploy script.<\/p>\n\n<p>Our script is really simple we are going to take our two smart contracts, and deploy them both, first, we need to deploy the <code>pair<\/code> smart contract since the <code>factory<\/code> smart contract needs a reference to that one.<\/p>\n\n<p>Our script will first check if we are on any of the Avalanche networks, and if so will deploy the smart contracts using a real wallet (with some AVAX in it), if not we will assume that we are on our local network and deploy them there.<\/p>\n\n<p>To deploy to a live blockchain (Fuji or Mainnet) we need to have a wallet with some AVAX on it, <a href=\"https:\/\/faucet.avax.network\/\">you can get some testnet AVAX tokens on this faucet<\/a>. Also, we need to define our <code>brownie-config.yaml<\/code> file to let Brownie know where to find our private key, and some important configurations as well.<\/p>\n\n<p>Create a <code>brownie-config.yaml<\/code> on the root of your project. It should look something like this.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">dotenv<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.env<\/span>\n\n<span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">default<\/span><span class=\"pi\">:<\/span> <span class=\"s\">hardhat<\/span>\n\n<span class=\"na\">wallets<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">from_key<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${PRIVATE_KEY}<\/span>\n\n<span class=\"na\">compiler<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">vyper<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">0.3.7\"<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The configuration file is expecting a <code>.env<\/code> file to work properly, create one on the root of your project and populate it with this.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>PRIVATE_KEY=\"YOUR_PRIVATE_KEY_HERE\"\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After we have our configuration setup, we need to write our deploy script. On the <code>scripts<\/code> folder create a new file called <code>deploy.py<\/code> this python program will be responsible for deploying our smart contracts.<\/p>\n\n<p>The <code>deploy.py<\/code> file should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">from<\/span> <span class=\"nn\">brownie<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">network<\/span><span class=\"p\">,<\/span> <span class=\"n\">config<\/span><span class=\"p\">,<\/span> <span class=\"n\">AvaSwapFactory<\/span><span class=\"p\">,<\/span> <span class=\"n\">AvaSwapPair<\/span>\n\n\n<span class=\"k\">def<\/span> <span class=\"nf\">main<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">supported_networks<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"s\">\"avax-mainnet\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"avax-testnet\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">active_network<\/span> <span class=\"o\">=<\/span> <span class=\"n\">network<\/span><span class=\"p\">.<\/span><span class=\"n\">show_active<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">active_network<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">supported_networks<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">deployer<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">.<\/span><span class=\"n\">add<\/span><span class=\"p\">(<\/span><span class=\"n\">config<\/span><span class=\"p\">[<\/span><span class=\"s\">\"wallets\"<\/span><span class=\"p\">][<\/span><span class=\"s\">\"from_key\"<\/span><span class=\"p\">])<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">deployer<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n\n    <span class=\"n\">ava_swap_pair<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapPair<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">({<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">deployer<\/span><span class=\"p\">})<\/span> \n    <span class=\"n\">ava_swap_factory<\/span> <span class=\"o\">=<\/span> <span class=\"n\">AvaSwapFactory<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">ava_swap_pair<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">\"from\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">deployer<\/span><span class=\"p\">})<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To run this script write the following command on your terminal, this will deploy the contract to your hardhat local node.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To deploy it to a testnet write the following one.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy <span class=\"nt\">--network<\/span> avax-testnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And to deploy them to the Avalanche mainnet run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy <span class=\"nt\">--network<\/span> avax-mainnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that would be it on the smart contract side, we created, tested, and deployed our AMM smart contracts.<\/p>\n\n<h2>\n  \n  \n  Conclusion\n<\/h2>\n\n<p>Automatic Market Makers are a wonderful tool used in the decentralized finance space, it allows users to swap tokens without \"normal\" market makers almost instantly. These kinds of smart contracts have a lot of use cases, and you can expand a lot more on this automatic market maker idea. Be creative!<\/p>\n\n","category":["web3","blockchain","react","python"]},{"title":"Constant Product Market Maker (CAMM): The standard in Decentralized Finance","pubDate":"Wed, 11 Jan 2023 21:41:48 +0000","link":"https:\/\/dev.to\/rabuawad\/constant-product-market-maker-cpmm-the-standard-in-decentralized-finance-2e2k","guid":"https:\/\/dev.to\/rabuawad\/constant-product-market-maker-cpmm-the-standard-in-decentralized-finance-2e2k","description":"<p>Decentralized finance (DeFi) has been gaining a lot of momentum in recent years, and Automated Market Maker (AMM) has been a key technology driving this trend. AMMs are decentralized exchanges (DEXs) that allow users to trade cryptocurrencies without the need for an intermediary. However, a breed of AMM called Constant Product Market Maker (CPMM) is the dominant implementation DeFi space.<\/p>\n\n<h3>\n  \n  \n  How CPMMs are useful\n<\/h3>\n\n<p>CPMMs are useful for several reasons:<\/p>\n\n<ul>\n<li>\n<strong>Efficient liquidity provision<\/strong>: CPMMs are designed to provide liquidity more efficiently than traditional AMMs. They do this by using a constant product formula which ensures that the liquidity pool is always in a balanced state, no matter how much the prices fluctuate. This results in lower slippage for users and more predictable pricing for traders.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li>\n<strong>Lower impermanent loss<\/strong>: Traditional AMMs can have a problem called impermanent loss (IL) where liquidity providers can experience a loss if the price of the asset changes. CPMMs, on the other hand, have a lower IL, as the constant product formula helps to minimize the impact of price fluctuations on liquidity providers.<\/li>\n<\/ul>\n\n\n\n<ul>\n<li>\n<strong>Better token price stability<\/strong>: CPMMs are better suited for stablecoin markets as they are less sensitive to price fluctuations, ensuring a more stable token price.<\/li>\n<\/ul>\n\n\n\n<h3>\n  \n  \n  A Code Sample\n<\/h3>\n\n<p>Here is an example of a simple CPMM smart contract, written in the <a href=\"https:\/\/vyper.readthedocs.io\/en\/stable\/\" rel=\"noopener noreferrer\">Vyper<\/a> programming language:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.3\n<\/span><span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n\n<span class=\"n\">token0<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">token1<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">reserve0<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">reserve1<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n<span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<span class=\"n\">balanceOf<\/span><span class=\"p\">:<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">]<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">(<\/span><span class=\"n\">_token0<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_token1<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token0<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_token1<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_amount<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_amount<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_amount<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_amount<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">_reserve0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_reserve1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve0<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_reserve1<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">swap<\/span><span class=\"p\">(<\/span><span class=\"n\">_tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span> <span class=\"ow\">or<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">invalid token<\/span><span class=\"sh\">\"<\/span> \n    <span class=\"k\">assert<\/span> <span class=\"n\">_amountIn<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">amount in is zero<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"n\">tokenIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC20<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">reserveIn<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"n\">reserveOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">_tokenIn<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">tokenIn<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">tokenOut<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">reserveIn<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span>\n        <span class=\"n\">reserveOut<\/span> <span class=\"o\">=<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span>\n\n    <span class=\"n\">tokenIn<\/span><span class=\"p\">.<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amountIn<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amountInWithFee<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_amountIn<\/span> <span class=\"o\">*<\/span> <span class=\"mi\">997<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">1000<\/span>\n    <span class=\"n\">amountOut<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveOut<\/span> <span class=\"o\">*<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"p\">(<\/span><span class=\"n\">reserveIn<\/span> <span class=\"o\">+<\/span> <span class=\"n\">amountInWithFee<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">tokenOut<\/span><span class=\"p\">.<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amountOut<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">),<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">))<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">amountOut<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">addLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">:<\/span>\n    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">self<\/span><span class=\"p\">,<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">if<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">or<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">assert<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span> <span class=\"o\">==<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve1<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">x \/ y != dx \/ dy<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"n\">shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">isqrt<\/span><span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">_amount1<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">else<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">shares<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">min<\/span><span class=\"p\">(<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">,<\/span>\n            <span class=\"p\">(<\/span><span class=\"n\">_amount0<\/span> <span class=\"o\">*<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">reserve0<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">)<\/span>\n\n    <span class=\"k\">assert<\/span> <span class=\"n\">shares<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">shares are zero<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">shares<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"k\">return<\/span> <span class=\"n\">shares<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">removeLiquidity<\/span><span class=\"p\">(<\/span><span class=\"n\">_shares<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">bal0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">bal1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">amount0<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal0<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n    <span class=\"n\">amount1<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"n\">_shares<\/span> <span class=\"o\">*<\/span> <span class=\"n\">bal1<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">amount0<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span> <span class=\"ow\">and<\/span> <span class=\"n\">amount1<\/span> <span class=\"o\">&gt;<\/span> <span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">amount0 or amount is zero<\/span><span class=\"sh\">\"<\/span>\n\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_shares<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_update<\/span><span class=\"p\">(<\/span><span class=\"n\">bal0<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">bal1<\/span> <span class=\"o\">-<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token0<\/span><span class=\"p\">).<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount0<\/span><span class=\"p\">)<\/span>\n    <span class=\"nc\">ERC20<\/span><span class=\"p\">(<\/span><span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">token1<\/span><span class=\"p\">).<\/span><span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"nf\">return <\/span><span class=\"p\">(<\/span><span class=\"n\">amount0<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount1<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>This example is quite basic, most real-world AMM smart contracts use more complex mechanisms to calculate prices and determine the amounts of assets that are exchanged in a trade.<\/p>\n\n<p>In the code above the contract provide the functionality to deposit, withdraw and trade assets on a pool, the trading functionality uses the current state of the pool to determine the amounts of assets that are exchanged, you could use a different mechanism to price the assets like a constant product or a bonding curve.<\/p>\n\n<p>Please keep in mind that, this is just a sample code, it should not be used in production as is, it lacks many important aspects such<\/p>\n\n","category":"webdev"},{"title":"Create a Wrapped ERC20 token on Avalanche with Vyper! \ud83d\udc0d\ud83e\ude99","pubDate":"Thu, 01 Dec 2022 03:14:24 +0000","link":"https:\/\/dev.to\/rabuawad\/create-a-wrapped-erc20-token-on-avalanche-with-vyper-1827","guid":"https:\/\/dev.to\/rabuawad\/create-a-wrapped-erc20-token-on-avalanche-with-vyper-1827","description":"<h2>\n  \n  \n  Introduction\n<\/h2>\n\n<p>In this article, we will describe the use cases of an ERC20 token and explain how to create one from scratch using Vyper, and we will deploy it to the Avalanche Fuji test network.<\/p>\n\n<h2>\n  \n  \n  Prerequisites\n<\/h2>\n\n<ul>\n<li>Basic programming and console\/terminal use experience<\/li>\n<li>A simple understanding of Solidity or Vyper<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  Requirements\n<\/h2>\n\n<ul>\n<li><a href=\"https:\/\/nodejs.org\/en\/\" rel=\"noopener noreferrer\">NodeJS<\/a><\/li>\n<li>\n<a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer\">Python<\/a> and <a href=\"https:\/\/eth-brownie.readthedocs.io\/\" rel=\"noopener noreferrer\">Brownie ETH<\/a>, or any smart contract framework<\/li>\n<li>\n<a href=\"https:\/\/code.visualstudio.com\/\" rel=\"noopener noreferrer\">VSCode<\/a>, or another code editor<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  What is an ERC20?\n<\/h2>\n\n<p>An ERC20 smart contract keeps track of fungible tokens, and the contract itself allows us to transfer, burn, and do much interesting stuff with that particular token.<\/p>\n\n<p>The interface itself is really simple and doesn't include a lot of information about the token itself.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># Functions\n<\/span><span class=\"nf\">totalSupply<\/span><span class=\"p\">()<\/span>\n<span class=\"nf\">balanceOf<\/span><span class=\"p\">(<\/span><span class=\"n\">account<\/span><span class=\"p\">)<\/span>\n<span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">to<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">)<\/span>\n<span class=\"nf\">allowance<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">,<\/span> <span class=\"n\">spender<\/span><span class=\"p\">)<\/span>\n<span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">)<\/span>\n<span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"k\">from<\/span><span class=\"p\">,<\/span> <span class=\"n\">to<\/span><span class=\"p\">,<\/span> <span class=\"n\">amount<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>These six functions are the original function defined on the EIP20, we can extend a lot of functionality by adding more functions (more features) to our smart contract.<\/p>\n\n<p>In this article we are going to create an ERC20 smart contract, that takes in AVAX and returns WAVAX, our wrapped implementation of the cryptocurrency. <\/p>\n\n<p>We are going to allow the users to mint tokens by depositing AVAX and burn tokens and get AVAX in return.<\/p>\n\n<h2>\n  \n  \n  Why they are important?\n<\/h2>\n\n<p>Tokens are a fundamental part of the web3 space, they can be used in a lot of creative and unique ways, like shares in a community, transactional value, currency in a protocol, and much more. In this tutorial, we are going to create a token that wraps a cryptocurrency (AVAX in this case) and that token can be used in defi protocols, web3 protocols, and more.<\/p>\n\n<h2>\n  \n  \n  Setup\n<\/h2>\n\n<p>We are going to use <a href=\"https:\/\/eth-brownie.readthedocs.io\" rel=\"noopener noreferrer\">Brownie<\/a> in this tutorial, <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/install.html\" rel=\"noopener noreferrer\">after you installed Brownie<\/a>, create a new folder called <code>avalanche-swap<\/code> and inside it run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie init\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Also, we are going to be using the Hardhat node to test our smart contracts, so inside your project folder, run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>npm <span class=\"nb\">install<\/span> <span class=\"nt\">--save-dev<\/span> hardhat\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Smart contract\n<\/h2>\n\n<p>Let's start with the boilerplate code. We create a file named <code>contracts\/WAVAX.vy<\/code>, define the vyper version as &gt;= 0.3.7, and import the ERC20 and ERC20 Detailed interfaces from vyper.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.7\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Events\n<\/h3>\n\n<p>We need to define our <code>events<\/code>, these are messages that the smart contract emits when called and the ones that we're defining at what the EIP20 proposed.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  State\n<\/h3>\n\n<p>Our smart contract needs state, or variables that will persist across the entire life of the smart contract. These variables contain information that is going to be useful to our users and to the methods that we will define below, like <code>balanceOf<\/code>, <code>totalSupply<\/code>, and <code>allowance<\/code><br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @dev name of the token (\"Wrapped AVAX\")\n<\/span><span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev symbol or ticker of the token (\"WAVAX\")\n<\/span><span class=\"n\">symbol<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev the amount of decimals the token contains\n<\/span><span class=\"n\">decimals<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint8<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># @dev the balance of a particular address\n<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev addresses can allow other's addresses to spend their tokens\n<\/span><span class=\"n\">allowance<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># @dev the number of tokens in circulation\n<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>As you can see we define a variable to store how many decimals our token will have, this is because <a href=\"https:\/\/docs.soliditylang.org\/en\/v0.8.17\/\" rel=\"noopener noreferrer\">Solidity<\/a>, the main programming langue used on EVM blockchains, has no support for using decimals, and we define decimals like integers, for example, we want to use 2 decimals, to express the number 100.99, we would put it like this 10099, being the last to digits the actual decimal part.<\/p>\n\n<h3>\n  \n  \n  Constructor\n<\/h3>\n\n<p>After that is complete we now define the constructor. Here we specify the name of the token, the symbol, and the number of decimals this token will have.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Wrapped AVAX<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">symbol<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">WAVAX<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">decimals<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">18<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Internal methods\n<\/h3>\n\n<p>The internal methods are really simple we need a method to mint our Wrapped AVAX tokens if the user sends the amount that they want and on to burn them to retrieve their tokens.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"nf\">send<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>These two methods are standard on ERC20 implementations, since we need a way to mint the tokens, and (if we choose so) burn them as well.<\/p>\n\n<h2>\n  \n  \n  External methods\n<\/h2>\n\n<p>We now need to define the main methods of an ERC20 token, <code>transfer<\/code>, <code>transferFrom<\/code>, and <code>approve<\/code>. These three methods allow our token holders to use the tokens however they want.<\/p>\n\n<p>The <code>transfer<\/code> method is self-explanatory and allows the token holder to transfer tokens to another user or a smart contract.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The token standard needs a <code>approve<\/code> method, to enable the <code>transferFrom<\/code> method that we define next. The <code>approve<\/code> method gives the token holder a way to allow another account to manage a defined amount of tokens for them.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">][<\/span><span class=\"n\">_spender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Approval<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And the <code>transferFrom<\/code> method gives the user the ability to another account to transfer tokens on behalf of the token holder or to manage a set amount of tokens for them.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Since this is a wrapped token, we need a way to receive the cryptocurrency that we are trying to wrap and mint an equivalent amount of tokens, and also a way to do this in reverse, burn several tokens and receive the equivalent cryptocurrency back.<\/p>\n\n<p>For the <code>mint<\/code> method, the user sends some cryptocurrency with the method call and gets the same amount back in tokens.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"nd\">@payable<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">mint<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And for the <code>burn<\/code> method, the user passes the number of tokens they want to burn, to receive the equivalent in cryptocurrency.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>We will also define a <strong>default method<\/strong>, this method will be triggered if a user sends some AVAX to the contract directly, without calling the <code>mint<\/code> function. And in turn, the contract will mint that user the equivalent in tokens.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"nd\">@external<\/span>\n<span class=\"nd\">@payable<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__default__<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that would be it. Now we have a token smart contract, that mints wrapped tokens. Yours should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># @version &gt;=0.3.7\n<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"kn\">from<\/span> <span class=\"n\">vyper.interfaces<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20<\/span>\n<span class=\"n\">implements<\/span><span class=\"p\">:<\/span> <span class=\"n\">ERC20Detailed<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Transfer<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">sender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">receiver<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"n\">event<\/span> <span class=\"n\">Approval<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">owner<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">spender<\/span><span class=\"p\">:<\/span> <span class=\"nf\">indexed<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span>\n\n<span class=\"c1\"># @dev name of the token (\"Wrapped AVAX\")\n<\/span><span class=\"n\">name<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev symbol or ticker of the token (\"WAVAX\")\n<\/span><span class=\"n\">symbol<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">String<\/span><span class=\"p\">[<\/span><span class=\"mi\">32<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev the amount of decimals the token contains\n<\/span><span class=\"n\">decimals<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint8<\/span><span class=\"p\">)<\/span>\n\n<span class=\"c1\"># @dev the balance of a particular address\n<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">])<\/span>\n\n<span class=\"c1\"># @dev addresses can allow other's addresses to spend their tokens\n<\/span><span class=\"n\">allowance<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">HashMap<\/span><span class=\"p\">[<\/span><span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">]])<\/span>\n\n<span class=\"c1\"># @dev the number of tokens in circulation\n<\/span><span class=\"n\">totalSupply<\/span><span class=\"p\">:<\/span> <span class=\"nf\">public<\/span><span class=\"p\">(<\/span><span class=\"n\">uint256<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__init__<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">name<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">Wrapped AVAX<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">symbol<\/span> <span class=\"o\">=<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">WAVAX<\/span><span class=\"sh\">\"<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">decimals<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">18<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@internal<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">_to<\/span> <span class=\"o\">!=<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">totalSupply<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"nf\">send<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"nf\">empty<\/span><span class=\"p\">(<\/span><span class=\"n\">address<\/span><span class=\"p\">),<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">approve<\/span><span class=\"p\">(<\/span><span class=\"n\">_spender<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">][<\/span><span class=\"n\">_spender<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Approval<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_spender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">transferFrom<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span> <span class=\"p\">:<\/span> <span class=\"n\">address<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span> <span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">)<\/span> <span class=\"o\">-&gt;<\/span> <span class=\"nb\">bool<\/span><span class=\"p\">:<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">balanceOf<\/span><span class=\"p\">[<\/span><span class=\"n\">_to<\/span><span class=\"p\">]<\/span> <span class=\"o\">+=<\/span> <span class=\"n\">_value<\/span>\n\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"n\">allowance<\/span><span class=\"p\">[<\/span><span class=\"n\">_from<\/span><span class=\"p\">][<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">]<\/span> <span class=\"o\">-=<\/span> <span class=\"n\">_value<\/span>\n    <span class=\"n\">log<\/span> <span class=\"nc\">Transfer<\/span><span class=\"p\">(<\/span><span class=\"n\">_from<\/span><span class=\"p\">,<\/span> <span class=\"n\">_to<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">return<\/span> <span class=\"bp\">True<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"nd\">@payable<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">mint<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">burn<\/span><span class=\"p\">(<\/span><span class=\"n\">_value<\/span><span class=\"p\">:<\/span> <span class=\"n\">uint256<\/span><span class=\"p\">):<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">_value<\/span><span class=\"p\">)<\/span>\n\n\n<span class=\"nd\">@external<\/span>\n<span class=\"nd\">@payable<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">__default__<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">self<\/span><span class=\"p\">.<\/span><span class=\"nf\">_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">value<\/span><span class=\"p\">)<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h2>\n  \n  \n  Deploy using <a href=\"https:\/\/eth-brownie.readthedocs.io\/\" rel=\"noopener noreferrer\">Brownie<\/a>\n<\/h2>\n\n<p>In this tutorial, we are going to use Brownie to deploy our smart contracts, you can use any other smart contract framework if you are familiar with it <a href=\"https:\/\/hardhat.org\/\" rel=\"noopener noreferrer\">Hardhat<\/a> or <a href=\"https:\/\/academy.apeworx.io\/\" rel=\"noopener noreferrer\">ApeWorx<\/a> both have support for developing and deploying vyper smart contracts.<\/p>\n\n<p>Since we are deploying to Avalanche, we need to add the Avalanche mainnet and the Avalanche Fuji testnet to our supported networks. In our terminal type the following:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie networks add Avalanche avax-testnet <span class=\"nv\">host<\/span><span class=\"o\">=<\/span>https:\/\/api.avax-test.network\/ext\/bc\/C\/rpc <span class=\"nv\">chainid<\/span><span class=\"o\">=<\/span>43113 <span class=\"nv\">explorer<\/span><span class=\"o\">=<\/span>https:\/\/testnet.snowtrace.io\/ <span class=\"nv\">name<\/span><span class=\"o\">=<\/span>Fuji\n<\/code><\/pre>\n\n<\/div>\n\n\n\n\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie networks add Avalanche avax-mainnet <span class=\"nv\">host<\/span><span class=\"o\">=<\/span>https:\/\/api.avax.network\/ext\/bc\/C\/rpc <span class=\"nv\">chainid<\/span><span class=\"o\">=<\/span>43114 <span class=\"nv\">explorer<\/span><span class=\"o\">=<\/span>https:\/\/snowtrace.io\/ <span class=\"nv\">name<\/span><span class=\"o\">=<\/span>Mainnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After we run these two commands brownie will add Avalanche to Brownie.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code>Avalanche\n  \u251c\u2500Mainnet: avax-mainnet\n  \u2514\u2500Fuji: avax-testnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After that is complete, you can write our deploy script.<\/p>\n\n<p>Our script is really simple we are going to take our smart contract, and deploy it.<\/p>\n\n<p>Our script will first check if we are on any of the Avalanche networks, and if so will deploy the smart contracts using a real wallet (with some AVAX in it), if not we will assume that we are on our local network and deploy them there.<\/p>\n\n<p>To deploy to a live blockchain (Fuji or Mainnet) we need to have a wallet with some AVAX on it, <a href=\"https:\/\/faucet.avax.network\/\" rel=\"noopener noreferrer\">you can get some testnet AVAX tokens on this faucet<\/a>. Also, we need to define our <code>brownie-config.yaml<\/code> file to let Brownie know where to find our private key, and some important configurations as well.<\/p>\n\n<p>Create a <code>brownie-config.yaml<\/code> on the root of your project. It should look something like this.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"na\">dotenv<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.env<\/span>\n\n<span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">default<\/span><span class=\"pi\">:<\/span> <span class=\"s\">hardhat<\/span>\n\n<span class=\"na\">wallets<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">from_key<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${PRIVATE_KEY}<\/span>\n\n<span class=\"na\">compiler<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">vyper<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">0.3.7\"<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The configuration file is expecting a <code>.env<\/code> file to work properly, create one on the root of your project and populate it with this.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight plaintext\"><code>PRIVATE_KEY=\"YOUR_PRIVATE_KEY_HERE\"\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After we have our configuration setup, we need to write our deploy script. On the <code>scripts<\/code> folder create a new file called <code>deploy.py<\/code> this python program will be responsible for deploying our smart contracts.<\/p>\n\n<p>The <code>deploy.py<\/code> file should look something like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">from<\/span> <span class=\"n\">brownie<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">network<\/span><span class=\"p\">,<\/span> <span class=\"n\">config<\/span><span class=\"p\">,<\/span> <span class=\"n\">WAVAX<\/span>\n\n\n<span class=\"k\">def<\/span> <span class=\"nf\">main<\/span><span class=\"p\">():<\/span>\n    <span class=\"n\">supported_networks<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">avax-mainnet<\/span><span class=\"sh\">\"<\/span><span class=\"p\">,<\/span> <span class=\"sh\">\"<\/span><span class=\"s\">avax-testnet<\/span><span class=\"sh\">\"<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">active_network<\/span> <span class=\"o\">=<\/span> <span class=\"n\">network<\/span><span class=\"p\">.<\/span><span class=\"nf\">show_active<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"n\">deployer<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n    <span class=\"k\">if<\/span> <span class=\"n\">active_network<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">supported_networks<\/span><span class=\"p\">:<\/span>\n        <span class=\"n\">deployer<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">.<\/span><span class=\"nf\">add<\/span><span class=\"p\">(<\/span><span class=\"n\">config<\/span><span class=\"p\">[<\/span><span class=\"sh\">\"<\/span><span class=\"s\">wallets<\/span><span class=\"sh\">\"<\/span><span class=\"p\">][<\/span><span class=\"sh\">\"<\/span><span class=\"s\">from_key<\/span><span class=\"sh\">\"<\/span><span class=\"p\">])<\/span>\n\n    <span class=\"n\">WAVAX<\/span><span class=\"p\">.<\/span><span class=\"nf\">deploy<\/span><span class=\"p\">({<\/span><span class=\"sh\">\"<\/span><span class=\"s\">from<\/span><span class=\"sh\">\"<\/span><span class=\"p\">:<\/span> <span class=\"n\">deployer<\/span><span class=\"p\">})<\/span> \n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To run this script write the following command on your terminal, this will deploy the contract to your hardhat local node.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>To deploy it to a testnet write the following one.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy <span class=\"nt\">--network<\/span> avax-testnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And to deploy them to the Avalanche mainnet run the following command:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight shell\"><code><span class=\"nv\">$ <\/span>brownie run deploy <span class=\"nt\">--network<\/span> avax-mainnet\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that would be it on the smart contract side, we created, tested, and deployed our wrapped token smart contract.<\/p>\n\n<h2>\n  \n  \n  Testnet smart contract (Fuji)\n<\/h2>\n\n<p><a href=\"https:\/\/testnet.snowtrace.io\/address\/0x4e9f59b082280c802922eb166d36cf1439ad0f17\" rel=\"noopener noreferrer\">WAVAX<\/a><\/p>\n\n","category":"restapi"},{"title":"Create a simple minting DApp using NextJS, Brownie, Solidity and TailwindCSS.","pubDate":"Wed, 23 Mar 2022 01:18:13 +0000","link":"https:\/\/dev.to\/rabuawad\/create-a-simple-minting-dapp-using-nextjs-brownie-solidity-and-tailwindcss-29g9","guid":"https:\/\/dev.to\/rabuawad\/create-a-simple-minting-dapp-using-nextjs-brownie-solidity-and-tailwindcss-29g9","description":"<h2>\n  \n  \n  Features\n<\/h2>\n\n<ul>\n<li>Let's the user create an NFT, with an image and metadata (properties)<\/li>\n<li>Stores and displays the NFTs the user owns<\/li>\n<li>Collect fees from every mint<\/li>\n<li>Dark\/Light mode<\/li>\n<\/ul>\n\n<h2>\n  \n  \n  Summary\n<\/h2>\n\n<p>In this tutorial, we will create an NFT minting web application, that allows users to upload an Image to IPFS, add properties and attributes, and mint a custom-made NFT.<\/p>\n\n<h2>\n  \n  \n  Setup\n<\/h2>\n\n<p>For this you will need to have installed <a href=\"https:\/\/www.python.org\/\">python<\/a>, <a href=\"https:\/\/nodejs.org\/en\/\">node.js<\/a> and <a href=\"https:\/\/eth-brownie.readthedocs.io\/en\/stable\/\">brownie-eth<\/a>. <\/p>\n\n<p>We also need a local blockchain to test and develop our application, I'll be using <a href=\"https:\/\/trufflesuite.com\/ganache\/index.html\">Ganache<\/a>, which is a beginner-friendly app to run a local blockchain, and there is a lot of tutorial and documentation on how to use it.<\/p>\n\n<p>After that, open your terminal and run <em>brownie bake react simple-mint<\/em>, this will generate  Brownie project using ReactJS, but wait I said that we will use NextJS for this project, go to the folder <em>simple-mint<\/em> (the project that you just created) and delete the folder called <em>client<\/em>. After that is done go back to your terminal and inside the <em>simple-mint<\/em> folder run <em>npx create-next-app client<\/em>, this command will create a brand new NextJS project. For now, that's all we need now onto the smart contracts!<\/p>\n\n<h2>\n  \n  \n  Smart contracts\n<\/h2>\n\n<p>Before we start programming the smart contract, we need to modify the <code>brownie-config.yaml<\/code>, here we will include the dependencies we need, re-mappings for the compiler, also now that we are here, create a <code>.env<\/code> file to avoid annoying errors.<\/p>\n\n<p>The <code>brownie-config.yaml<\/code> file should now look like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight yaml\"><code><span class=\"c1\"># change the build directory to be within react's scope<\/span>\n<span class=\"na\">project_structure<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">build<\/span><span class=\"pi\">:<\/span> <span class=\"s\">client\/artifacts<\/span>\n\n\n<span class=\"na\">dependencies<\/span><span class=\"pi\">:<\/span>\n    <span class=\"pi\">-<\/span> <span class=\"s\">OpenZeppelin\/openzeppelin-contracts@4.5.0<\/span>\n\n\n<span class=\"c1\"># automatically fetch contract sources from Etherscan<\/span>\n<span class=\"na\">autofetch_sources<\/span><span class=\"pi\">:<\/span> <span class=\"s\">True<\/span>\n<span class=\"na\">dotenv<\/span><span class=\"pi\">:<\/span> <span class=\"s\">.env<\/span>\n\n\n<span class=\"na\">compiler<\/span><span class=\"pi\">:<\/span>\n    <span class=\"na\">solc<\/span><span class=\"pi\">:<\/span>\n        <span class=\"na\">version<\/span><span class=\"pi\">:<\/span> <span class=\"s1\">'<\/span><span class=\"s\">0.8.4'<\/span>\n        <span class=\"na\">optimizer<\/span><span class=\"pi\">:<\/span>\n            <span class=\"na\">enabled<\/span><span class=\"pi\">:<\/span> <span class=\"no\">true<\/span>\n            <span class=\"na\">runs<\/span><span class=\"pi\">:<\/span> <span class=\"m\">200<\/span>\n        <span class=\"na\">remappings<\/span><span class=\"pi\">:<\/span>\n            <span class=\"pi\">-<\/span> <span class=\"s2\">\"<\/span><span class=\"s\">@openzeppelin=OpenZeppelin\/openzeppelin-contracts@4.5.0\"<\/span>\n\n\n<span class=\"na\">networks<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">default<\/span><span class=\"pi\">:<\/span> <span class=\"s\">development<\/span>\n  <span class=\"na\">development<\/span><span class=\"pi\">:<\/span>\n\n    <span class=\"na\">update_interval<\/span><span class=\"pi\">:<\/span> <span class=\"m\">60<\/span>\n    <span class=\"na\">verify<\/span><span class=\"pi\">:<\/span> <span class=\"s\">False<\/span>\n\n  <span class=\"na\">kovan<\/span><span class=\"pi\">:<\/span>\n\n    <span class=\"na\">verify<\/span><span class=\"pi\">:<\/span> <span class=\"s\">False<\/span>\n    <span class=\"na\">update_interval<\/span><span class=\"pi\">:<\/span> <span class=\"m\">60<\/span>\n\n\n<span class=\"na\">wallets<\/span><span class=\"pi\">:<\/span>\n  <span class=\"na\">from_key<\/span><span class=\"pi\">:<\/span> <span class=\"s\">${PRIVATE_KEY}<\/span>\n\n\n<span class=\"c1\"># enable output of development artifacts to load with react<\/span>\n<span class=\"na\">dev_deployment_artifacts<\/span><span class=\"pi\">:<\/span> <span class=\"no\">true<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>For this dapp we only need one smart contract, the contract is really simple is an extended version of an ERC-721 contract. Inside the <em>contracts<\/em> folder create a <code>SimpleMint.sol<\/code> file.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight solidity\"><code><span class=\"c1\">\/\/ SPDX-License-Identifier: MIT\n\/\/ contracts\/SimpleMint.sol\n<\/span><span class=\"k\">pragma<\/span> <span class=\"n\">solidity<\/span> <span class=\"o\">^<\/span><span class=\"mf\">0.8<\/span><span class=\"p\">.<\/span><span class=\"mi\">4<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ Te will extend\/use this open zeppelin smart contract to save time\n\/\/ if you nee more information about ERC721 checkout the OpenZeppelin docs\n\/\/ https:\/\/docs.openzeppelin.com\/contracts\/4.x\/erc721\n<\/span><span class=\"k\">import<\/span> <span class=\"s\">\"@openzeppelin\/contracts\/token\/ERC721\/ERC721.sol\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"s\">\"@openzeppelin\/contracts\/token\/ERC721\/extensions\/ERC721URIStorage.sol\"<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"s\">\"@openzeppelin\/contracts\/utils\/Counters.sol\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"c1\">\/\/ This smart contract enabled us to give access control to some functions\n\/\/ https:\/\/docs.openzeppelin.com\/contracts\/4.x\/api\/access#Ownable\n<\/span><span class=\"k\">import<\/span> <span class=\"s\">\"@openzeppelin\/contracts\/access\/Ownable.sol\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"k\">contract<\/span> <span class=\"n\">SimpleMint<\/span> <span class=\"k\">is<\/span> <span class=\"n\">ERC721<\/span><span class=\"p\">,<\/span> <span class=\"n\">ERC721URIStorage<\/span><span class=\"p\">,<\/span> <span class=\"n\">Ownable<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">using<\/span> <span class=\"n\">Counters<\/span> <span class=\"k\">for<\/span> <span class=\"n\">Counters<\/span><span class=\"p\">.<\/span><span class=\"n\">Counter<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"n\">Counters<\/span><span class=\"p\">.<\/span><span class=\"n\">Counter<\/span> <span class=\"k\">private<\/span> <span class=\"n\">_tokenIdCounter<\/span><span class=\"p\">;<\/span>\n    <span class=\"c1\">\/\/ This is the minting fee users have to pay to mint an NFT\n<\/span>    <span class=\"c1\">\/\/ on the platform\n<\/span>    <span class=\"kt\">uint256<\/span> <span class=\"k\">private<\/span> <span class=\"n\">_fee<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.0025<\/span> <span class=\"kc\">ether<\/span><span class=\"p\">;<\/span>\n\n    <span class=\"k\">constructor<\/span><span class=\"p\">()<\/span> <span class=\"n\">ERC721<\/span><span class=\"p\">(<\/span><span class=\"s\">\"SimpleMint\"<\/span><span class=\"p\">,<\/span> <span class=\"s\">\"SIMPLE\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{}<\/span>\n\n    <span class=\"k\">function<\/span> <span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"kt\">string<\/span> <span class=\"k\">memory<\/span> <span class=\"n\">uri<\/span><span class=\"p\">)<\/span> <span class=\"k\">public<\/span> <span class=\"k\">payable<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ This 'require' ensures the user is paying\n<\/span>        <span class=\"c1\">\/\/ the minting fee\n<\/span>        <span class=\"nb\">require<\/span> <span class=\"p\">(<\/span>\n            <span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">value<\/span> <span class=\"o\">==<\/span> <span class=\"n\">_fee<\/span><span class=\"p\">,<\/span>\n            <span class=\"s\">\"You nee to pay a small fee to mint the NFT.\"<\/span>\n        <span class=\"p\">);<\/span>\n\n        <span class=\"kt\">uint256<\/span> <span class=\"n\">tokenId<\/span> <span class=\"o\">=<\/span> <span class=\"n\">_tokenIdCounter<\/span><span class=\"p\">.<\/span><span class=\"n\">current<\/span><span class=\"p\">();<\/span>\n        <span class=\"n\">_tokenIdCounter<\/span><span class=\"p\">.<\/span><span class=\"n\">increment<\/span><span class=\"p\">();<\/span>\n        <span class=\"n\">_safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">msg<\/span><span class=\"p\">.<\/span><span class=\"n\">sender<\/span><span class=\"p\">,<\/span> <span class=\"n\">tokenId<\/span><span class=\"p\">);<\/span>\n        <span class=\"n\">_setTokenURI<\/span><span class=\"p\">(<\/span><span class=\"n\">tokenId<\/span><span class=\"p\">,<\/span> <span class=\"n\">uri<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ The following functions are overrides required by Solidity.\n<\/span>\n    <span class=\"k\">function<\/span> <span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span> <span class=\"n\">tokenId<\/span><span class=\"p\">)<\/span> <span class=\"k\">internal<\/span> <span class=\"k\">override<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC721<\/span><span class=\"p\">,<\/span> <span class=\"n\">ERC721URIStorage<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nb\">super<\/span><span class=\"p\">.<\/span><span class=\"n\">_burn<\/span><span class=\"p\">(<\/span><span class=\"n\">tokenId<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">function<\/span> <span class=\"n\">tokenURI<\/span><span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span> <span class=\"n\">tokenId<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">public<\/span>\n        <span class=\"k\">view<\/span>\n        <span class=\"k\">override<\/span><span class=\"p\">(<\/span><span class=\"n\">ERC721<\/span><span class=\"p\">,<\/span> <span class=\"n\">ERC721URIStorage<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">returns<\/span> <span class=\"p\">(<\/span><span class=\"kt\">string<\/span> <span class=\"k\">memory<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"nb\">super<\/span><span class=\"p\">.<\/span><span class=\"n\">tokenURI<\/span><span class=\"p\">(<\/span><span class=\"n\">tokenId<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ This function will return a list of Token URIs\n<\/span>    <span class=\"c1\">\/\/ given an Ethreum address\n<\/span>    <span class=\"k\">function<\/span> <span class=\"n\">tokensOf<\/span><span class=\"p\">(<\/span><span class=\"kt\">address<\/span> <span class=\"n\">minter<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">public<\/span>\n        <span class=\"k\">view<\/span>\n        <span class=\"k\">returns<\/span> <span class=\"p\">(<\/span><span class=\"kt\">string<\/span><span class=\"p\">[]<\/span> <span class=\"k\">memory<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ Here we count how many tokens does the user have \n<\/span>        <span class=\"kt\">uint256<\/span> <span class=\"n\">count<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">for<\/span><span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span> <span class=\"n\">i<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">_tokenIdCounter<\/span><span class=\"p\">.<\/span><span class=\"n\">current<\/span><span class=\"p\">();<\/span> <span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"n\">ownerOf<\/span><span class=\"p\">(<\/span><span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">minter<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n                <span class=\"n\">count<\/span> <span class=\"o\">++<\/span><span class=\"p\">;<\/span>\n            <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"c1\">\/\/ Here we create and populate the tokens with their\n<\/span>        <span class=\"c1\">\/\/ correspoding Token URI\n<\/span>        <span class=\"kt\">string<\/span><span class=\"p\">[]<\/span> <span class=\"k\">memory<\/span> <span class=\"n\">tokens<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"kt\">string<\/span><span class=\"p\">[](<\/span><span class=\"n\">count<\/span><span class=\"p\">);<\/span>\n        <span class=\"kt\">uint256<\/span> <span class=\"n\">index<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">for<\/span><span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span> <span class=\"n\">i<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span> <span class=\"n\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"n\">_tokenIdCounter<\/span><span class=\"p\">.<\/span><span class=\"n\">current<\/span><span class=\"p\">();<\/span> <span class=\"n\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n            <span class=\"k\">if<\/span><span class=\"p\">(<\/span><span class=\"n\">ownerOf<\/span><span class=\"p\">(<\/span><span class=\"n\">i<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">minter<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n                <span class=\"n\">tokens<\/span><span class=\"p\">[<\/span><span class=\"n\">index<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"n\">tokenURI<\/span><span class=\"p\">(<\/span><span class=\"n\">i<\/span><span class=\"p\">);<\/span>\n                <span class=\"n\">index<\/span> <span class=\"o\">++<\/span><span class=\"p\">;<\/span>\n            <span class=\"p\">}<\/span>\n        <span class=\"p\">}<\/span>\n\n        <span class=\"k\">return<\/span> <span class=\"n\">tokens<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ This function returns the minting fee to users\n<\/span>    <span class=\"k\">function<\/span> <span class=\"n\">fee<\/span><span class=\"p\">()<\/span>\n        <span class=\"k\">public<\/span>\n        <span class=\"k\">view<\/span>\n        <span class=\"k\">returns<\/span> <span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"k\">return<\/span> <span class=\"n\">_fee<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ This function allows you, **and only you**, to change \n<\/span>    <span class=\"c1\">\/\/ the minting fee\n<\/span>    <span class=\"k\">function<\/span> <span class=\"n\">setFee<\/span><span class=\"p\">(<\/span><span class=\"kt\">uint256<\/span> <span class=\"n\">newFee<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">public<\/span>\n        <span class=\"n\">onlyOwner<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"n\">_fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">newFee<\/span><span class=\"p\">;<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ This function will transfer all the fees collected\n<\/span>    <span class=\"c1\">\/\/ to the owner\n<\/span>    <span class=\"k\">function<\/span> <span class=\"n\">withdraw<\/span><span class=\"p\">()<\/span>\n        <span class=\"k\">public<\/span>\n        <span class=\"n\">onlyOwner<\/span>\n    <span class=\"p\">{<\/span>\n        <span class=\"p\">(<\/span><span class=\"kt\">bool<\/span> <span class=\"n\">success<\/span><span class=\"p\">,<\/span> <span class=\"p\">)<\/span> <span class=\"o\">=<\/span> <span class=\"k\">payable<\/span><span class=\"p\">(<\/span><span class=\"n\">owner<\/span><span class=\"p\">()).<\/span><span class=\"nb\">call<\/span><span class=\"p\">{<\/span> <span class=\"n\">value<\/span><span class=\"o\">:<\/span> <span class=\"kt\">address<\/span><span class=\"p\">(<\/span><span class=\"nb\">this<\/span><span class=\"p\">).<\/span><span class=\"nb\">balance<\/span> <span class=\"p\">}(<\/span><span class=\"s\">\"\"<\/span><span class=\"p\">);<\/span>\n        <span class=\"nb\">require<\/span> <span class=\"p\">(<\/span><span class=\"n\">success<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Well, that's it, this is the smart contract that will be the backbone of our application.<\/p>\n\n<h2>\n  \n  \n  Testing\n<\/h2>\n\n<p>Before we deploy this dapp to production, we need to make sure everything is working properly, for this we will write some automated tests that will check if the functionality of the smart contract is what we expect.<\/p>\n\n<p>Go to the <em>tests<\/em> folder, and open the <code>conftest.py<\/code>  file, this is code that will execute before each test. The file should be looking like this:<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/conftest.py\n<\/span><span class=\"kn\">import<\/span> <span class=\"nn\">pytest<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">autouse<\/span><span class=\"o\">=<\/span><span class=\"bp\">True<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">setup<\/span><span class=\"p\">(<\/span><span class=\"n\">fn_isolation<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Isolation setup fixture.\n    This ensures that each test runs against the same base environment.\n    \"\"\"<\/span>\n    <span class=\"k\">pass<\/span>\n\n\n<span class=\"o\">@<\/span><span class=\"n\">pytest<\/span><span class=\"p\">.<\/span><span class=\"n\">fixture<\/span><span class=\"p\">(<\/span><span class=\"n\">scope<\/span><span class=\"o\">=<\/span><span class=\"s\">\"module\"<\/span><span class=\"p\">)<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">simple_mint<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">SimpleMint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Yield a `Contract` object for the SimpleMint contract.\n    \"\"\"<\/span>\n    <span class=\"k\">yield<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"n\">deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">SimpleMint<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now create a file called <code>test_simple_mint.py<\/code> inside the <em>tests<\/em> folder. The first test that we will write is to check if the contract is deployed correctly.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/test_simple_mint.py\n<\/span><span class=\"kn\">from<\/span> <span class=\"nn\">brownie<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">Wei<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">test_simple_mint_deploy<\/span><span class=\"p\">(<\/span><span class=\"n\">simple_mint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Test if the contract is correctly deployed.\n    \"\"\"<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'0.0025 ether'<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now we create a test to check if the user can and cannot mint NFTs while paying the fee.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/test_simple_mint.py\n# ...\n<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">test_simple_mint_minting<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Test if the contract can mint an NFT, and charge the\n    corresponding fee.\n    \"\"\"<\/span>\n    <span class=\"n\">token_uri<\/span> <span class=\"o\">=<\/span> <span class=\"s\">'https:\/\/example.mock\/uri.json'<\/span>\n\n    <span class=\"c1\"># can't mint, not paying fee\n<\/span>    <span class=\"k\">with<\/span> <span class=\"n\">reverts<\/span><span class=\"p\">():<\/span>\n        <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># can mint, paying fee\n<\/span>    <span class=\"n\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>The next test will check the display of user tokens after minting, and if the owner of the token is correct, this means that the users can only see NFTs that they own.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/test_simple_mint.py\n# ...\n<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">test_simple_mint_tokens<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Test if the contract can mint an NFT, and charge the\n    corresponding fee.\n    \"\"\"<\/span>\n    <span class=\"n\">token_uri<\/span> <span class=\"o\">=<\/span> <span class=\"s\">'https:\/\/example.mock\/uri.json'<\/span>\n    <span class=\"n\">user_one<\/span><span class=\"p\">,<\/span> <span class=\"n\">user_two<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">2<\/span><span class=\"p\">]<\/span>\n    <span class=\"n\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c1\"># minting 3 tokens as user one\n<\/span>    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">user_one<\/span><span class=\"p\">,<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">user_one<\/span><span class=\"p\">,<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">user_one<\/span><span class=\"p\">,<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n\n    <span class=\"c1\"># minting 2 tokens as user two\n<\/span>    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">user_two<\/span><span class=\"p\">,<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">user_two<\/span><span class=\"p\">,<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n\n\n    <span class=\"n\">user_one_tokens<\/span> <span class=\"o\">=<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">tokensOf<\/span><span class=\"p\">(<\/span><span class=\"n\">user_one<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">user_one_tokens<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">3<\/span>\n\n    <span class=\"c1\"># here we assert that the owner of the token is the correct one\n<\/span>    <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"s\">\"--- user one's tokens\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"n\">token_id<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">user_one_tokens<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">assert<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">ownerOf<\/span><span class=\"p\">(<\/span><span class=\"n\">token_id<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">user_one<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n        <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"n\">token_id<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"n\">user_two_tokens<\/span> <span class=\"o\">=<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">tokensOf<\/span><span class=\"p\">(<\/span><span class=\"n\">user_two<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"nb\">len<\/span><span class=\"p\">(<\/span><span class=\"n\">user_two_tokens<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">2<\/span>\n\n    <span class=\"c1\"># here we assert that the owner of the token is the correct one\n<\/span>    <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"s\">\"--- user two's tokens\"<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"n\">token_id<\/span> <span class=\"ow\">in<\/span> <span class=\"n\">user_two_tokens<\/span><span class=\"p\">:<\/span>\n        <span class=\"k\">assert<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">ownerOf<\/span><span class=\"p\">(<\/span><span class=\"n\">token_id<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">user_two<\/span><span class=\"p\">.<\/span><span class=\"n\">address<\/span>\n        <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"n\">token_id<\/span><span class=\"p\">)<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>We will test the fee-related functions, first, we will test if we can change the minting fee.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/test_simple_mint.py\n# ...\n<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">test_simple_mint_fees<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Test if the owner, and the owner only, can change the minting fee.\n    \"\"\"<\/span>\n\n    <span class=\"n\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'0.0025 ether'<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># another user cannot change the minting fee\n<\/span>    <span class=\"k\">with<\/span> <span class=\"n\">reverts<\/span><span class=\"p\">():<\/span>\n        <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">setFee<\/span><span class=\"p\">(<\/span><span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'0.5 ether'<\/span><span class=\"p\">),<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># the owner can change the minting fee\n<\/span>    <span class=\"n\">new_fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'0.0025 ether'<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">setFee<\/span><span class=\"p\">(<\/span><span class=\"n\">new_fee<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">fee<\/span><span class=\"p\">()<\/span> <span class=\"o\">==<\/span> <span class=\"n\">new_fee<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Finally, we will test the withdrawal function, and check if we got the correct amount of collected fees.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"c1\"># tests\/test_simple_mint.py\n# ...\n<\/span>\n<span class=\"k\">def<\/span> <span class=\"nf\">test_simple_withdraw<\/span><span class=\"p\">(<\/span><span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">simple_mint<\/span><span class=\"p\">):<\/span>\n    <span class=\"s\">\"\"\"\n    Test if the owner, and the owner only, can withdraw all the\n    collected fees.\n    \"\"\"<\/span>\n    <span class=\"n\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'0.5 ether'<\/span><span class=\"p\">)<\/span>\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">setFee<\/span><span class=\"p\">(<\/span><span class=\"n\">fee<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n    <span class=\"n\">initial_balance<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"n\">balance<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s\">'Intial balance: <\/span><span class=\"si\">{<\/span><span class=\"n\">initial_balance<\/span><span class=\"si\">}<\/span><span class=\"s\">'<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\"># here we will mint 10 tokens, at a 0.5 ETH fee, this will cost 5 ETH\n<\/span>    <span class=\"c1\"># to account one, so the collected fees should amount to 5 ETH\n<\/span>    <span class=\"n\">token_uri<\/span> <span class=\"o\">=<\/span> <span class=\"s\">'https:\/\/example.mock\/uri.json'<\/span>\n    <span class=\"k\">for<\/span> <span class=\"n\">i<\/span> <span class=\"ow\">in<\/span> <span class=\"nb\">range<\/span><span class=\"p\">(<\/span><span class=\"mi\">10<\/span><span class=\"p\">):<\/span>\n        <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s\">'mint <\/span><span class=\"si\">{<\/span><span class=\"n\">i<\/span><span class=\"si\">}<\/span><span class=\"s\">\/10'<\/span><span class=\"p\">)<\/span>\n        <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">safeMint<\/span><span class=\"p\">(<\/span>\n            <span class=\"n\">token_uri<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">1<\/span><span class=\"p\">],<\/span> <span class=\"s\">'value'<\/span><span class=\"p\">:<\/span> <span class=\"n\">fee<\/span><span class=\"p\">})<\/span>\n\n    <span class=\"n\">simple_mint<\/span><span class=\"p\">.<\/span><span class=\"n\">withdraw<\/span><span class=\"p\">({<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n    <span class=\"c1\"># the owner new balance should be:\n<\/span>    <span class=\"c1\"># initial_balance + 5 ETH\n<\/span>    <span class=\"n\">new_balance<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"n\">balance<\/span><span class=\"p\">()<\/span>\n    <span class=\"k\">print<\/span><span class=\"p\">(<\/span><span class=\"sa\">f<\/span><span class=\"s\">'New balance: <\/span><span class=\"si\">{<\/span><span class=\"n\">new_balance<\/span><span class=\"si\">}<\/span><span class=\"s\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">assert<\/span> <span class=\"n\">initial_balance<\/span> <span class=\"o\">+<\/span> <span class=\"n\">Wei<\/span><span class=\"p\">(<\/span><span class=\"s\">'5 ether'<\/span><span class=\"p\">)<\/span> <span class=\"o\">==<\/span> <span class=\"n\">new_balance<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that's it for testing, <strong>we checked the basic functionality that the smart contract needs to have<\/strong>.<\/p>\n\n<p>To run the tests open <em>ganache<\/em>, once ganache is running a local blockchain, you can go back to your terminal\/console and run the following command <code>brownie test<\/code>, this will run all the tests that we have written (you can also run <code>brownie test -s<\/code> to view prints and more details on each test).<\/p>\n\n<p>If you want to see how the code is structured, check out the <a href=\"https:\/\/github.com\/rafael-abuawad\/simple-mint\">code repository<\/a>.<\/p>\n\n<h2>\n  \n  \n  Front-end\n<\/h2>\n\n<p>Now go back to your terminal, and go to the <em>client<\/em> folder, we need to install some dependencies, go check the <a href=\"https:\/\/tailwindcss.com\/docs\/guides\/nextjs\">setup guide for TailwindCSS with NextJS<\/a>, after that is complete we need to install some package to interact with a blockchain from NextJS, run <code>npm install web3modal ethers Axios ipfs-http-client<\/code>, once that is installed we can start building our front-end.<\/p>\n\n<h2>\n  \n  \n  Components\n<\/h2>\n\n<p>First, we will build all the components that we need to have to use the application, take in mind these are dumb components, which means that they will not interact with the state directly.<\/p>\n\n<h3>\n  \n  \n  Loading component\n<\/h3>\n\n<p>A simple component to display an overlay, with a spinning wheel and some text. The text is variable, to allow you to display any message that you want.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/Loading\/index.js<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">Loading<\/span><span class=\"p\">({<\/span> <span class=\"nx\">text<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"overflow-none fixed top-0 left-0 flex h-screen w-screen items-center justify-center bg-black bg-opacity-50\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center text-white\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">svg<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"-ml-1 mr-3 h-5 w-5 animate-spin text-white\"<\/span>\n          <span class=\"na\">xmlns<\/span><span class=\"p\">=<\/span><span class=\"s\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n          <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none\"<\/span>\n          <span class=\"na\">viewBox<\/span><span class=\"p\">=<\/span><span class=\"s\">\"0 0 24 24\"<\/span>\n        <span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">circle<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"opacity-25\"<\/span>\n            <span class=\"na\">cx<\/span><span class=\"p\">=<\/span><span class=\"s\">\"12\"<\/span>\n            <span class=\"na\">cy<\/span><span class=\"p\">=<\/span><span class=\"s\">\"12\"<\/span>\n            <span class=\"na\">r<\/span><span class=\"p\">=<\/span><span class=\"s\">\"10\"<\/span>\n            <span class=\"na\">stroke<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">strokeWidth<\/span><span class=\"p\">=<\/span><span class=\"s\">\"4\"<\/span>\n          <span class=\"p\">&gt;&lt;\/<\/span><span class=\"nt\">circle<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">path<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"opacity-75\"<\/span>\n            <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">d<\/span><span class=\"p\">=<\/span><span class=\"s\">\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\"<\/span>\n          <span class=\"p\">&gt;&lt;\/<\/span><span class=\"nt\">path<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">svg<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">text<\/span><span class=\"si\">}<\/span>...\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Navbar\n<\/h3>\n\n<p>The first component we will create is a navbar, to navigate between views and connect our web3 wallet to the application. This component displays a 'connect wallet button' and the logo, once the user connects the 'connect wallet button' will disappear and the wallet address and navigation links will show up. This component also has the theme toggler button, although the button is fixed since this component will be used in every view is better to have it here.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/Navbar\/index.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Image<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/image<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Link<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/link<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ This returns a **readable** wallet address<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">formatAddress<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">address<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n  <span class=\"nx\">address<\/span><span class=\"p\">.<\/span><span class=\"nx\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">5<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">...<\/span><span class=\"dl\">'<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">address<\/span><span class=\"p\">.<\/span><span class=\"nx\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">38<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">Navbar<\/span><span class=\"p\">({<\/span> <span class=\"nx\">address<\/span><span class=\"p\">,<\/span> <span class=\"nx\">connectWallet<\/span><span class=\"p\">,<\/span> <span class=\"nx\">theme<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setTheme<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"py-6 md:px-6\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center justify-center border-b border-zinc-100 px-3 pb-6 dark:border-zinc-600 sm:justify-between\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"cm\">\/* logo *\/<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"hidden cursor-pointer sm:inline-flex\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">Image<\/span> <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/logo.png\"<\/span> <span class=\"na\">width<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">90<\/span><span class=\"si\">}<\/span> <span class=\"na\">height<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">78<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n\n        <span class=\"si\">{<\/span><span class=\"cm\">\/* connect button *\/<\/span><span class=\"si\">}<\/span>\n        <span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">address<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span>\n              <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">connectWallet<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"cursor-pointer rounded-md bg-green-400 py-2 px-3 text-white hover:bg-green-500\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Connect\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n\n        <span class=\"si\">{<\/span><span class=\"cm\">\/* navigation &amp; user's address *\/<\/span><span class=\"si\">}<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">address<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex items-center space-x-3\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"hover:underline\"<\/span><span class=\"p\">&gt;<\/span>My NFTs<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/create\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"hover:underline\"<\/span><span class=\"p\">&gt;<\/span>Create<span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"rounded-md bg-green-400 py-2 px-3 text-white\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">formatAddress<\/span><span class=\"p\">(<\/span><span class=\"nx\">address<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"cm\">\/* theme toggler *\/<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fixed -bottom-1 -right-1 rounded-md border border-zinc-100 bg-white bg-zinc-50 p-3 dark:border-zinc-600 dark:bg-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">theme<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">light<\/span><span class=\"dl\">'<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">svg<\/span>\n            <span class=\"na\">cursor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pointer\"<\/span>\n            <span class=\"na\">xmlns<\/span><span class=\"p\">=<\/span><span class=\"s\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-6 w-6\"<\/span>\n            <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none\"<\/span>\n            <span class=\"na\">viewBox<\/span><span class=\"p\">=<\/span><span class=\"s\">\"0 0 24 24\"<\/span>\n            <span class=\"na\">stroke<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">strokeWidth<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">2<\/span><span class=\"si\">}<\/span>\n            <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setTheme<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">dark<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">path<\/span>\n              <span class=\"na\">strokeLinecap<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">strokeLinejoin<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">d<\/span><span class=\"p\">=<\/span><span class=\"s\">\"M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z\"<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">svg<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">theme<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">dark<\/span><span class=\"dl\">'<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">svg<\/span>\n            <span class=\"na\">cursor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pointer\"<\/span>\n            <span class=\"na\">xmlns<\/span><span class=\"p\">=<\/span><span class=\"s\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-6 w-6\"<\/span>\n            <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none\"<\/span>\n            <span class=\"na\">viewBox<\/span><span class=\"p\">=<\/span><span class=\"s\">\"0 0 24 24\"<\/span>\n            <span class=\"na\">stroke<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">strokeWidth<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">2<\/span><span class=\"si\">}<\/span>\n            <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setTheme<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">light<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">path<\/span>\n              <span class=\"na\">strokeLinecap<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">strokeLinejoin<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">d<\/span><span class=\"p\">=<\/span><span class=\"s\">\"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z\"<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">svg<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  No wallet\n<\/h3>\n\n<p>This is a simple component to prompt the user to connect their wallet to the user of the application.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/NoWallet\/index.js<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">NoWallet<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex h-screen w-screen items-center justify-center md:h-[65vh]\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"font-3xl font-bold text-zinc-400 dark:text-zinc-200\"<\/span><span class=\"p\">&gt;<\/span>\n        Connect your wallet to access the application\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  No Mints\n<\/h3>\n\n<p>We also need a <strong>no mints<\/strong> component, to show the user that he hasn't created an NFT with that address.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/NoMints\/index.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Link<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/link<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">NoMints<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex h-screen w-full items-center justify-center md:h-[65vh]\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"font-3xl font-bold text-zinc-400 dark:text-zinc-200\"<\/span><span class=\"p\">&gt;<\/span>\n        Looks like you haven't created any NFT's yet,<span class=\"si\">{<\/span><span class=\"dl\">'<\/span><span class=\"s1\"> <\/span><span class=\"dl\">'<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/create\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"cursor-pointer text-green-500 hover:underline\"<\/span><span class=\"p\">&gt;<\/span>\n            creaate one now\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n        .\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  NFT Card\n<\/h3>\n\n<p>This component will display the image and the name of the NFT that the user owns\/mints, and will also include a link to a details page of that NFT.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/NFTCard\/index.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Link<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/link<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Image<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/image<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">NFTCard<\/span><span class=\"p\">({<\/span> <span class=\"nx\">data<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"max-w-96 group relative h-72 cursor-pointer rounded-md duration-100 ease-in-out hover:scale-105 sm:w-72\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"max-w-96 relative h-72 rounded-md sm:w-72\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">Image<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"rounded-md\"<\/span>\n          <span class=\"na\">layout<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fill\"<\/span>\n          <span class=\"na\">objectFit<\/span><span class=\"p\">=<\/span><span class=\"s\">\"cover\"<\/span>\n          <span class=\"na\">quality<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">100<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">image<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">alt<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n        <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none absolute bottom-0 flex hidden h-12 w-full items-center rounded-b-md bg-zinc-800 px-3 font-bold text-white ease-in-out group-hover:flex dark:bg-white dark:text-zinc-800 \"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">Link<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"s2\">`\/details\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">tokenId<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">a<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"hover:text-green-300 hover:underline\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">a<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Link<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Details\n<\/h3>\n\n<p>This is a wrapper component, a dropdown to display the details from an NFT. The details themselfs can be anything that you want, and the component can either display them on a grid or not.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/Details\/index.js<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">Details<\/span><span class=\"p\">({<\/span> <span class=\"nx\">summary<\/span><span class=\"p\">,<\/span> <span class=\"nx\">isGrid<\/span><span class=\"p\">,<\/span> <span class=\"nx\">children<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">details<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"group border border-zinc-100 p-3 hover:cursor-pointer dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">summary<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"font-xl flex w-full list-none items-center justify-between font-bold\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"cm\">\/* The title of the drop down *\/<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">span<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"group-hover:underline\"<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">summary<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">span<\/span><span class=\"p\">&gt;<\/span>\n\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">svg<\/span>\n            <span class=\"na\">xmlns<\/span><span class=\"p\">=<\/span><span class=\"s\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-6 w-6\"<\/span>\n            <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none\"<\/span>\n            <span class=\"na\">viewBox<\/span><span class=\"p\">=<\/span><span class=\"s\">\"0 0 24 24\"<\/span>\n            <span class=\"na\">stroke<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">strokeWidth<\/span><span class=\"p\">=<\/span><span class=\"s\">\"2\"<\/span>\n          <span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">path<\/span>\n              <span class=\"na\">strokeLinecap<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">strokeLinejoin<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">d<\/span><span class=\"p\">=<\/span><span class=\"s\">\"M19 9l-7 7-7-7\"<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">svg<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">summary<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"cm\">\/* if its children should be in a grid *\/<\/span><span class=\"si\">}<\/span>\n      <span class=\"si\">{<\/span><span class=\"nx\">isGrid<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"grid grid-flow-row grid-cols-2 gap-4 pt-3 md:grid-cols-3 xl:grid-cols-4\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"cm\">\/* else *\/<\/span><span class=\"si\">}<\/span>\n      <span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">isGrid<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pt-3 text-zinc-800 dark:text-zinc-50\"<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">children<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">details<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Details tile\n<\/h3>\n\n<p>This component will be used inside the details component, and it will display properties and attributes from the NFT, is really simple.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/DetailTile\/index.js<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">DetailTile<\/span><span class=\"p\">({<\/span> <span class=\"nx\">title<\/span><span class=\"p\">,<\/span> <span class=\"nx\">value<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex h-32 w-full flex-col items-center justify-center rounded-md border border-zinc-100 p-3 dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-3xl text-zinc-800 dark:text-zinc-50\"<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-xl font-bold text-green-500\"<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">title<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Add attributes form\n<\/h3>\n\n<p>This component will be used in the create  NFT view, it will be responsible of handle the logic to add an attribute, an attribute is stored inside the metadata of an NFT, in the attributes array, which gives it unique properties and values.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/AddAttributes\/index.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ A function to capitalize text<\/span>\n<span class=\"c1\">\/\/ Ex. capitalize(\"soME TeXT\") =&gt; \"Some Text\"<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">capitalize<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">text<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n  <span class=\"nx\">text<\/span>\n    <span class=\"p\">.<\/span><span class=\"nx\">trim<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">.<\/span><span class=\"nx\">toLowerCase<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">.<\/span><span class=\"nx\">split<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\"> <\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">word<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">word<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">].<\/span><span class=\"nx\">toUpperCase<\/span><span class=\"p\">()<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">word<\/span><span class=\"p\">.<\/span><span class=\"nx\">slice<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span><span class=\"p\">))<\/span>\n    <span class=\"p\">.<\/span><span class=\"nx\">join<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\"> <\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">AddAttributes<\/span><span class=\"p\">({<\/span> <span class=\"nx\">addAttribute<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ ERC-721 metadata attributes<\/span>\n  <span class=\"c1\">\/\/ {<\/span>\n  <span class=\"c1\">\/\/    \"display_type\": \"boost_number\",<\/span>\n  <span class=\"c1\">\/\/    \"trait_type\": \"Aqua Power\",<\/span>\n  <span class=\"c1\">\/\/    \"value\": 40<\/span>\n  <span class=\"c1\">\/\/ }<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">displayType<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setDisplayType<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">traitType<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setTraitType<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">text<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">value<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setValue<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"kd\">function<\/span> <span class=\"nx\">handleAddAttribute<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">preventDefault<\/span><span class=\"p\">()<\/span>\n\n    <span class=\"c1\">\/\/ if one field is empty return<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">displayType<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"kd\">let<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span> <span class=\"na\">displayType<\/span><span class=\"p\">:<\/span> <span class=\"nx\">capitalize<\/span><span class=\"p\">(<\/span><span class=\"nx\">displayType<\/span><span class=\"p\">),<\/span> <span class=\"nx\">traitType<\/span><span class=\"p\">,<\/span> <span class=\"nx\">value<\/span> <span class=\"p\">}<\/span>\n    <span class=\"k\">switch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">capitalize<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">break<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_percentage<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Number<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">%<\/span><span class=\"dl\">'<\/span>\n        <span class=\"k\">break<\/span>\n      <span class=\"p\">}<\/span>\n      <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_number<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span>\n      <span class=\"k\">case<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">number<\/span><span class=\"dl\">'<\/span><span class=\"p\">:<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Number<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span>\n        <span class=\"k\">break<\/span>\n      <span class=\"p\">}<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"nx\">addAttribute<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\">\/\/ reset all fields<\/span>\n    <span class=\"nx\">setDisplayType<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n    <span class=\"nx\">setTraitType<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">text<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"nx\">setValue<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">form<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex h-16 w-full items-center space-x-3\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n          <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n        <span class=\"p\">&gt;<\/span>\n          Name\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">input<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"placeholder-text-xl h-12 rounded-md border-2 border-zinc-100 bg-zinc-100 px-2 py-1 outline-none focus:border-green-400 dark:border-zinc-500 dark:bg-zinc-500\"<\/span>\n          <span class=\"na\">id<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n          <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">displayType<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">placeholder<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Ex. Power\"<\/span>\n          <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setDisplayType<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n          <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"traitType\"<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n        <span class=\"p\">&gt;<\/span>\n          Trait Type\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">select<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"placeholder-text-xl h-12 rounded-md border-2 border-zinc-100 bg-zinc-100 px-2 py-1 outline-none focus:border-green-400 dark:border-zinc-500 dark:bg-zinc-500\"<\/span>\n          <span class=\"na\">name<\/span><span class=\"p\">=<\/span><span class=\"s\">\"traitType\"<\/span>\n          <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">traitType<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setTraitType<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span><span class=\"p\">&gt;<\/span>Text<span class=\"p\">&lt;\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"s\">\"boost_percentage\"<\/span><span class=\"p\">&gt;<\/span>Boost Percentage<span class=\"p\">&lt;\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"s\">\"boost_number\"<\/span><span class=\"p\">&gt;<\/span>Boost Number<span class=\"p\">&lt;\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">option<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"s\">\"number\"<\/span><span class=\"p\">&gt;<\/span>Number<span class=\"p\">&lt;\/<\/span><span class=\"nt\">option<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">select<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n          <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"value\"<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n        <span class=\"p\">&gt;<\/span>\n          Value\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">input<\/span>\n          <span class=\"na\">id<\/span><span class=\"p\">=<\/span><span class=\"s\">\"value\"<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"placeholder-text-xl h-12 rounded-md border-2 border-zinc-100 bg-zinc-100 px-2 py-1 outline-none focus:border-green-400 dark:border-zinc-500 dark:bg-zinc-500\"<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n          <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span>\n          <span class=\"na\">placeholder<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Ex. 25\"<\/span>\n          <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setValue<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex w-12 flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span>\n          <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mt-5 flex h-12 w-12 items-center justify-center rounded-md bg-green-400 text-white hover:bg-green-500\"<\/span>\n          <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"submit\"<\/span>\n          <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">handleAddAttribute<\/span><span class=\"si\">}<\/span>\n        <span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">svg<\/span>\n            <span class=\"na\">xmlns<\/span><span class=\"p\">=<\/span><span class=\"s\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span>\n            <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"h-6 w-6\"<\/span>\n            <span class=\"na\">fill<\/span><span class=\"p\">=<\/span><span class=\"s\">\"none\"<\/span>\n            <span class=\"na\">viewBox<\/span><span class=\"p\">=<\/span><span class=\"s\">\"0 0 24 24\"<\/span>\n            <span class=\"na\">stroke<\/span><span class=\"p\">=<\/span><span class=\"s\">\"currentColor\"<\/span>\n            <span class=\"na\">strokeWidth<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">4<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">path<\/span>\n              <span class=\"na\">strokeLinecap<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">strokeLinejoin<\/span><span class=\"p\">=<\/span><span class=\"s\">\"round\"<\/span>\n              <span class=\"na\">d<\/span><span class=\"p\">=<\/span><span class=\"s\">\"M12 6v6m0 0v6m0-6h6m-6 0H6\"<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">svg<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">form<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Attributes table\n<\/h3>\n\n<p>This component will be use to display the attributes as we add them.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ components\/AttributesTable\/index.js<\/span>\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">AttributesTable<\/span><span class=\"p\">({<\/span> <span class=\"nx\">attributes<\/span><span class=\"p\">,<\/span> <span class=\"nx\">removeAttribute<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ If there are no attributes, don't show anything<\/span>\n  <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">return<\/span> <span class=\"kc\">null<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">table<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"w-full border border-zinc-100 dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">thead<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 p-3 text-sm uppercase text-zinc-500 dark:border-zinc-600 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n            Name\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 p-3 text-sm uppercase text-zinc-500 dark:border-zinc-600 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n            Display Type\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 p-3 text-sm uppercase text-zinc-500 dark:border-zinc-600 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n            Value\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">th<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 p-3 text-sm uppercase text-zinc-500 dark:border-zinc-600 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n            Remove\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">th<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">thead<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">tbody<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">attribute<\/span><span class=\"p\">,<\/span> <span class=\"nx\">i<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">tr<\/span> <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">i<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 text-center dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">attribute<\/span><span class=\"p\">.<\/span><span class=\"nx\">displayType<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 text-center lowercase text-zinc-400 dark:border-zinc-600 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">attribute<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 text-center dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">attribute<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">td<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"border border-zinc-100 text-center dark:border-zinc-600\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span>\n                <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"my-1 rounded-md px-2 py-1 font-semibold text-red-500 hover:bg-red-500 hover:text-white\"<\/span>\n                <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">removeAttribute<\/span><span class=\"p\">(<\/span><span class=\"nx\">i<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&gt;<\/span>\n                REMOVE\n              <span class=\"p\">&lt;\/<\/span><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">td<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">tr<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">))<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">tbody<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">table<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Well, that's it for components, we separated the logic between components and pages, because components should be small pieces of code, not aware of the global state, this makes them easy to debug and easy to test.<\/p>\n\n<p>If you want to see how the code is structured, check out the <a href=\"https:\/\/github.com\/rafael-abuawad\/simple-mint\">code repository<\/a>.<\/p>\n\n<h2>\n  \n  \n  Pages\n<\/h2>\n\n<p>Here we will manage our context, our smart contracts, and all the logic that connects to something else. I don't expect you to be an expert with the Context API, but I would recommend you to take a look at how it works if you haven't already.<\/p>\n\n<p>First, we will create a Web3 Context, which will contain all the information about the smart contracts and the connected wallet. Go ahead, and inside the <code>client<\/code> folder create a file <code>store\/web3Context.js<\/code>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">createContext<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">createContext<\/span><span class=\"p\">({<\/span>\n  <span class=\"na\">simpleMint<\/span><span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">signer<\/span><span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">address<\/span><span class=\"p\">:<\/span> <span class=\"kc\">null<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">})<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>Now we will create the Theme Context, it may be a little more complex, but it only takes care of the app theme (light or dark).<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight javascript\"><code><span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">getInitialTheme<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"k\">typeof<\/span> <span class=\"nb\">window<\/span> <span class=\"o\">!==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">undefined<\/span><span class=\"dl\">'<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nx\">localStorage<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">storedPrefs<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nx\">getItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">color-theme<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"k\">typeof<\/span> <span class=\"nx\">storedPrefs<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">string<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"nx\">storedPrefs<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">userMedia<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nx\">matchMedia<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">(prefers-color-scheme: dark)<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">userMedia<\/span><span class=\"p\">.<\/span><span class=\"nx\">matches<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">dark<\/span><span class=\"dl\">'<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">light<\/span><span class=\"dl\">'<\/span> <span class=\"c1\">\/\/ light theme as the default;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">rawSetTheme<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">rawTheme<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">root<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">documentElement<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">isDark<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">rawTheme<\/span> <span class=\"o\">===<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">dark<\/span><span class=\"dl\">'<\/span>\n\n  <span class=\"nx\">root<\/span><span class=\"p\">.<\/span><span class=\"nx\">classList<\/span><span class=\"p\">.<\/span><span class=\"nx\">remove<\/span><span class=\"p\">(<\/span><span class=\"nx\">isDark<\/span> <span class=\"p\">?<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">light<\/span><span class=\"dl\">'<\/span> <span class=\"p\">:<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">dark<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n  <span class=\"nx\">root<\/span><span class=\"p\">.<\/span><span class=\"nx\">classList<\/span><span class=\"p\">.<\/span><span class=\"nx\">add<\/span><span class=\"p\">(<\/span><span class=\"nx\">rawTheme<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"nx\">localStorage<\/span><span class=\"p\">.<\/span><span class=\"nx\">setItem<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">color-theme<\/span><span class=\"dl\">'<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rawTheme<\/span><span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  <em>_app<\/em> page\n<\/h3>\n\n<p>This is a wrapper component, here we will put in place our contexts, and connect them to our web3 application. This page displays the NoWallet component if there is no wallet connected to the application.<\/p>\n\n<p>It does a lot of things, so take your time to read the comments.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Web3Modal<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">web3modal<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">ethers<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">ethers<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ components<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Navbar<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/Navbar<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">NoWallet<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/NoWallet<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ store and context<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getInitialTheme<\/span><span class=\"p\">,<\/span> <span class=\"nx\">rawSetTheme<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/store\/themeContext<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Web3Context<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">getNetworkName<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/store\/web3Context<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ styles<\/span>\n<span class=\"k\">import<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/styles\/globals.css<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ smart-contracts<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">SimpleMint<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/artifacts\/contracts\/SimpleMint.json<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"kd\">function<\/span> <span class=\"nx\">App<\/span><span class=\"p\">({<\/span> <span class=\"nx\">Component<\/span><span class=\"p\">,<\/span> <span class=\"nx\">pageProps<\/span> <span class=\"p\">})<\/span> <span class=\"p\">{<\/span>\n  <span class=\"c1\">\/\/ app theme<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">theme<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setTheme<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"nx\">getInitialTheme<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"c1\">\/\/ web3 dapp state<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">signer<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setSigner<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">address<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setAddress<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setSimpleMint<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"c1\">\/\/ sets the theme on change<\/span>\n  <span class=\"nx\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"nx\">rawSetTheme<\/span><span class=\"p\">(<\/span><span class=\"nx\">theme<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">theme<\/span><span class=\"p\">])<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">connectWallet<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">web3Modal<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nx\">Web3Modal<\/span><span class=\"p\">()<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">connection<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">web3Modal<\/span><span class=\"p\">.<\/span><span class=\"nx\">connect<\/span><span class=\"p\">()<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">provider<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nx\">ethers<\/span><span class=\"p\">.<\/span><span class=\"nx\">providers<\/span><span class=\"p\">.<\/span><span class=\"nx\">Web3Provider<\/span><span class=\"p\">(<\/span><span class=\"nx\">connection<\/span><span class=\"p\">)<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">signer<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">provider<\/span><span class=\"p\">.<\/span><span class=\"nx\">getSigner<\/span><span class=\"p\">()<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">address<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">signer<\/span><span class=\"p\">.<\/span><span class=\"nx\">getAddress<\/span><span class=\"p\">()<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">chainId<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">provider<\/span><span class=\"p\">.<\/span><span class=\"nx\">getNetwork<\/span><span class=\"p\">()<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">chainName<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">getNetworkName<\/span><span class=\"p\">(<\/span><span class=\"nx\">chainId<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\">\/\/ this deployed simple mint smartcontract address <\/span>\n    <span class=\"c1\">\/\/\/ *** REPLACE THIS ***<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">simpleMintAddress<\/span> <span class=\"o\">=<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">0x854b699d119c5f89681c96d282098e4420eDa135<\/span><span class=\"dl\">'<\/span>\n\n    <span class=\"kd\">const<\/span> <span class=\"nx\">simpleMintContract<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"nx\">ethers<\/span><span class=\"p\">.<\/span><span class=\"nx\">Contract<\/span><span class=\"p\">(<\/span>\n      <span class=\"nx\">simpleMintAddress<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">SimpleMint<\/span><span class=\"p\">.<\/span><span class=\"nx\">abi<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">signer<\/span>\n    <span class=\"p\">)<\/span>\n\n    <span class=\"nx\">setSigner<\/span><span class=\"p\">(<\/span><span class=\"nx\">signer<\/span><span class=\"p\">)<\/span>\n    <span class=\"nx\">setAddress<\/span><span class=\"p\">(<\/span><span class=\"nx\">address<\/span><span class=\"p\">)<\/span>\n    <span class=\"nx\">setSimpleMint<\/span><span class=\"p\">(<\/span><span class=\"nx\">simpleMintContract<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">Navbar<\/span>\n        <span class=\"na\">address<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">address<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">connectWallet<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">connectWallet<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">theme<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">theme<\/span><span class=\"si\">}<\/span>\n        <span class=\"na\">setTheme<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">setTheme<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">\/&gt;<\/span>\n      <span class=\"si\">{<\/span><span class=\"nx\">address<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nc\">Web3Context<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">{<\/span> <span class=\"nx\">signer<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span><span class=\"p\">,<\/span> <span class=\"nx\">simpleMint<\/span> <span class=\"p\">}<\/span><span class=\"si\">}<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nc\">Component<\/span> <span class=\"si\">{<\/span><span class=\"p\">...<\/span><span class=\"nx\">pageProps<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Web3Context<\/span><span class=\"p\">.<\/span><span class=\"nc\">Provider<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n      <span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">address<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">NoWallet<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">App<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Index Page\n<\/h3>\n\n<p>This is the main page, here we display the NFTs that the user owns, and if the user hasn't minted any NFTs yet we will display the NoMints component.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ pages\/index.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">axios<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">axios<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Head<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/head<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ store<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Web3Context<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/store\/web3Context<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ components<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">NFTCard<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/NFTCard<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">NoMints<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/NoMints<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">Home<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">Web3Context<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">nfts<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setNfts<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">([])<\/span>\n\n  <span class=\"c1\">\/\/ once connected a wallet load the nfts<\/span>\n  <span class=\"nx\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">simpleMint<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">address<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">loadNfts<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span><span class=\"p\">])<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">loadNfts<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">let<\/span> <span class=\"nx\">nfts<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">.<\/span><span class=\"nx\">tokensOf<\/span><span class=\"p\">(<\/span><span class=\"nx\">address<\/span><span class=\"p\">)<\/span>\n\n    <span class=\"c1\">\/\/ tokensOf returns a Token ID and a Token URI<\/span>\n    <span class=\"c1\">\/\/ we need to retrive and parse that data<\/span>\n    <span class=\"nx\">nfts<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nb\">Promise<\/span><span class=\"p\">.<\/span><span class=\"nx\">all<\/span><span class=\"p\">(<\/span>\n      <span class=\"nx\">nfts<\/span><span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">(<\/span><span class=\"k\">async<\/span> <span class=\"p\">(<\/span><span class=\"nx\">nft<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"c1\">\/\/ token as returned from the smart-contract<\/span>\n        <span class=\"kd\">let<\/span> <span class=\"p\">[<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">,<\/span> <span class=\"nx\">tokenId<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">nft<\/span>\n\n        <span class=\"c1\">\/\/ parsing the token id<\/span>\n        <span class=\"nx\">tokenId<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">tokenId<\/span><span class=\"p\">.<\/span><span class=\"nx\">toString<\/span><span class=\"p\">()<\/span>\n        <span class=\"c1\">\/\/ fetching the metadata<\/span>\n        <span class=\"nx\">metadata<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">axios<\/span><span class=\"p\">.<\/span><span class=\"kd\">get<\/span><span class=\"p\">(<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">).<\/span><span class=\"nx\">then<\/span><span class=\"p\">((<\/span><span class=\"nx\">res<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">)<\/span>\n\n        <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">metadata<\/span><span class=\"p\">,<\/span> <span class=\"nx\">tokenId<\/span> <span class=\"p\">}<\/span>\n      <span class=\"p\">})<\/span>\n    <span class=\"p\">)<\/span>\n\n    <span class=\"nx\">setNfts<\/span><span class=\"p\">(<\/span><span class=\"nx\">nfts<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>Simple Mint<span class=\"p\">&lt;\/<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">meta<\/span> <span class=\"na\">name<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span> <span class=\"na\">content<\/span><span class=\"p\">=<\/span><span class=\"s\">\"NFT minting Dapp\"<\/span> <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">link<\/span> <span class=\"na\">rel<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/favicon.ico\"<\/span> <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"px-3 md:px-6\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-3xl font-bold\"<\/span><span class=\"p\">&gt;<\/span>NFTs<span class=\"p\">&lt;\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">nfts<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">==<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">NoMints<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n        <span class=\"si\">{<\/span><span class=\"nx\">nfts<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">!=<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"sm: grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 p-3\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"si\">{<\/span><span class=\"nx\">nfts<\/span><span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">nft<\/span><span class=\"p\">,<\/span> <span class=\"nx\">i<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">NFTCard<\/span> <span class=\"na\">key<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">i<\/span><span class=\"si\">}<\/span> <span class=\"na\">data<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n            <span class=\"p\">))<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Create page\n<\/h3>\n\n<p>This page gives the user a great UI to create an NFT, without code.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ pages\/create.js<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">create<\/span> <span class=\"k\">as<\/span> <span class=\"nx\">ipfsHttpClient<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">ipfs-http-client<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useRouter<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/router<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Head<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/head<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Image<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/image<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ components<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">AddAttributes<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/AddAttributes<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">AttributesTable<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/AttributesTable<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Loading<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/components\/Loading<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ store<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Web3Context<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/store\/web3Context<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ IPFS access point<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">client<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">ipfsHttpClient<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">https:\/\/ipfs.infura.io:5001\/api\/v0<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">Create<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">Web3Context<\/span><span class=\"p\">)<\/span>\n  <span class=\"c1\">\/\/ we will use the router to change the view after creating the NFT<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">router<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRouter<\/span><span class=\"p\">()<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">name<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setName<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">description<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setDescription<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"dl\">''<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setAttributes<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">([])<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">imageUrl<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setImageUrl<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">uploading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setUploading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">loading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"c1\">\/\/ simple function to remove an attribute<\/span>\n  <span class=\"kd\">function<\/span> <span class=\"nx\">removeAttribute<\/span><span class=\"p\">(<\/span><span class=\"nx\">index<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"kd\">let<\/span> <span class=\"nx\">newAttributes<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\n    <span class=\"k\">for<\/span> <span class=\"p\">(<\/span><span class=\"kd\">let<\/span> <span class=\"nx\">i<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">0<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span> <span class=\"o\">&lt;<\/span> <span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span><span class=\"p\">;<\/span> <span class=\"nx\">i<\/span><span class=\"o\">++<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">i<\/span> <span class=\"o\">==<\/span> <span class=\"nx\">index<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">continue<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"nx\">newAttributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">push<\/span><span class=\"p\">(<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">[<\/span><span class=\"nx\">i<\/span><span class=\"p\">])<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"nx\">setAttributes<\/span><span class=\"p\">(<\/span><span class=\"nx\">newAttributes<\/span><span class=\"p\">)<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">uploadImage<\/span><span class=\"p\">(<\/span><span class=\"nx\">event<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">setUploading<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">)<\/span>\n\n      <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">files<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">files<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">0<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n        <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"nb\">Error<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">You must select an image to upload.<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n      <span class=\"p\">}<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">file<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">event<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">files<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">added<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">client<\/span><span class=\"p\">.<\/span><span class=\"nx\">add<\/span><span class=\"p\">(<\/span><span class=\"nx\">file<\/span><span class=\"p\">)<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">url<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`https:\/\/ipfs.infura.io\/ipfs\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">added<\/span><span class=\"p\">.<\/span><span class=\"nx\">path<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span>\n      <span class=\"nx\">setImageUrl<\/span><span class=\"p\">(<\/span><span class=\"nx\">url<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">alert<\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">setUploading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">createNft<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ all data is required to create an NFT<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">name<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">description<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">length<\/span> <span class=\"o\">===<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span><span class=\"nx\">imageUrl<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"k\">return<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"c1\">\/\/ collect all data into an object<\/span>\n    <span class=\"kd\">const<\/span> <span class=\"nx\">data<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">name<\/span><span class=\"p\">,<\/span>\n      <span class=\"na\">image<\/span><span class=\"p\">:<\/span> <span class=\"nx\">imageUrl<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">description<\/span><span class=\"p\">,<\/span>\n      <span class=\"nx\">attributes<\/span><span class=\"p\">,<\/span>\n    <span class=\"p\">}<\/span>\n\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">)<\/span>\n      <span class=\"c1\">\/\/ we parse the data as JSON before uploading it to IPFS<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">added<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">client<\/span><span class=\"p\">.<\/span><span class=\"nx\">add<\/span><span class=\"p\">(<\/span><span class=\"nx\">JSON<\/span><span class=\"p\">.<\/span><span class=\"nx\">stringify<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">))<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">url<\/span> <span class=\"o\">=<\/span> <span class=\"s2\">`https:\/\/ipfs.infura.io\/ipfs\/<\/span><span class=\"p\">${<\/span><span class=\"nx\">added<\/span><span class=\"p\">.<\/span><span class=\"nx\">path<\/span><span class=\"p\">}<\/span><span class=\"s2\">`<\/span>\n\n      <span class=\"c1\">\/\/ get the minting fee to mint the NFT<\/span>\n      <span class=\"kd\">let<\/span> <span class=\"nx\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">.<\/span><span class=\"nx\">fee<\/span><span class=\"p\">()<\/span>\n      <span class=\"nx\">fee<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">fee<\/span><span class=\"p\">.<\/span><span class=\"nx\">toString<\/span><span class=\"p\">()<\/span>\n\n      <span class=\"c1\">\/\/ wait till the transaction is confirmed<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">tx<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">.<\/span><span class=\"nx\">safeMint<\/span><span class=\"p\">(<\/span><span class=\"nx\">url<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span> <span class=\"na\">value<\/span><span class=\"p\">:<\/span> <span class=\"nx\">fee<\/span> <span class=\"p\">})<\/span>\n      <span class=\"k\">await<\/span> <span class=\"nx\">tx<\/span><span class=\"p\">.<\/span><span class=\"nx\">wait<\/span><span class=\"p\">()<\/span>\n\n      <span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nx\">push<\/span><span class=\"p\">(<\/span><span class=\"dl\">'<\/span><span class=\"s1\">\/<\/span><span class=\"dl\">'<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">alert<\/span><span class=\"p\">(<\/span><span class=\"nx\">error<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">finally<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>Create | Simple Mint<span class=\"p\">&lt;\/<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">meta<\/span> <span class=\"na\">name<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span> <span class=\"na\">content<\/span><span class=\"p\">=<\/span><span class=\"s\">\"NFT minting Dapp\"<\/span> <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">link<\/span> <span class=\"na\">rel<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/favicon.ico\"<\/span> <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">loading<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">Loading<\/span> <span class=\"na\">text<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Processing\"<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"px-3 md:px-6\"<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-3xl font-bold\"<\/span><span class=\"p\">&gt;<\/span>Create NFT<span class=\"p\">&lt;\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-col space-y-6 py-12\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n              <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mb-1 text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Image\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">input<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"err\">\"<\/span>\n                <span class=\"na\">block<\/span> <span class=\"na\">w-full<\/span> <span class=\"na\">cursor-pointer<\/span> <span class=\"na\">text-sm<\/span>\n                <span class=\"na\">text-slate-500<\/span> <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">mr-4<\/span> <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">rounded-full<\/span>\n                <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">border-0<\/span> <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">bg-green-400<\/span>\n                <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">py-2<\/span> <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">px-4<\/span>\n                <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">text-sm<\/span> <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">font-semibold<\/span>\n                <span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">text-white<\/span>\n                <span class=\"na\">hover<\/span><span class=\"err\">:<\/span><span class=\"na\">file<\/span><span class=\"err\">:<\/span><span class=\"na\">bg-green-500<\/span>\n              <span class=\"err\">\"<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"file\"<\/span>\n              <span class=\"na\">id<\/span><span class=\"p\">=<\/span><span class=\"s\">\"single\"<\/span>\n              <span class=\"na\">accept<\/span><span class=\"p\">=<\/span><span class=\"s\">\"image\/*\"<\/span>\n              <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">uploadImage<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">disabled<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">uploading<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n              <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"mb-1 text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Loaded Image\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"si\">{<\/span><span class=\"nx\">uploading<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"max-w-96 flex h-72 w-full animate-pulse items-center justify-center rounded-md bg-zinc-400\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>Loading...<span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n            <span class=\"si\">{<\/span><span class=\"o\">!<\/span><span class=\"nx\">uploading<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">imageUrl<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"max-w-96 relative h-72 rounded-md sm:w-72\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Image<\/span>\n                  <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"rounded-md\"<\/span>\n                  <span class=\"na\">layout<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fill\"<\/span>\n                  <span class=\"na\">objectFit<\/span><span class=\"p\">=<\/span><span class=\"s\">\"cover\"<\/span>\n                  <span class=\"na\">quality<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">100<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">imageUrl<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">alt<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n                <span class=\"p\">\/&gt;<\/span>\n              <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n              <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Name\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">input<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"placeholder-text-xl h-12 rounded-md border-2 border-zinc-100 bg-zinc-100 px-2 py-1 outline-none focus:border-green-400 dark:border-zinc-500 dark:bg-zinc-500 dark:focus:border-green-400\"<\/span>\n              <span class=\"na\">id<\/span><span class=\"p\">=<\/span><span class=\"s\">\"name\"<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n              <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">name<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">placeholder<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Ex. Power\"<\/span>\n              <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setName<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">label<\/span>\n              <span class=\"na\">htmlFor<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Description\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">label<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">textarea<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"placeholder-text-xl rounded-md border-2 border-zinc-100 bg-zinc-100 px-2 py-1 outline-none focus:border-green-400 dark:border-zinc-500 dark:bg-zinc-500 dark:focus:border-green-400\"<\/span>\n              <span class=\"na\">id<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span>\n              <span class=\"na\">type<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n              <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">description<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">placeholder<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Ex. Lorem ipsum dolor sit amet.\"<\/span>\n              <span class=\"na\">onChange<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setDescription<\/span><span class=\"p\">(<\/span><span class=\"nx\">e<\/span><span class=\"p\">.<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex flex-grow flex-col\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">AddAttributes<\/span>\n              <span class=\"na\">addAttribute<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"p\">(<\/span><span class=\"nx\">data<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">setAttributes<\/span><span class=\"p\">((<\/span><span class=\"nx\">prev<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">[...<\/span><span class=\"nx\">prev<\/span><span class=\"p\">,<\/span> <span class=\"nx\">data<\/span><span class=\"p\">])<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"flex-grow\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"pb-1 text-sm uppercase text-zinc-500 dark:text-zinc-300\"<\/span><span class=\"p\">&gt;<\/span>\n              Attributes\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nc\">AttributesTable<\/span>\n              <span class=\"na\">attributes<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">attributes<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">removeAttribute<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">removeAttribute<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">\/&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">button<\/span>\n              <span class=\"na\">onClick<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">createNft<\/span><span class=\"si\">}<\/span>\n              <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"w-full cursor-pointer rounded-md bg-green-400 py-2 px-3 text-white hover:bg-green-500\"<\/span>\n            <span class=\"p\">&gt;<\/span>\n              Create\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">button<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<h3>\n  \n  \n  Details page\n<\/h3>\n\n<p>This page is really self explenatory, it fetches and display data from an specific token. This page has a parameter, the token ID, <a href=\"https:\/\/nextjs.org\/docs\/routing\/dynamic-routes\">check the next docs for more information<\/a>.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight jsx\"><code><span class=\"c1\">\/\/ pages\/details\/[tokenId].js<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useEffect<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useState<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useRouter<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/router<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Head<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/head<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Image<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">next\/image<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">axios<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">axios<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ components<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Details<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/..\/components\/Details<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">DetailTile<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/..\/components\/DetailTile<\/span><span class=\"dl\">'<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Loading<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/..\/components\/Loading<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"c1\">\/\/ store<\/span>\n<span class=\"k\">import<\/span> <span class=\"nx\">Web3Context<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">..\/..\/store\/web3Context<\/span><span class=\"dl\">'<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">TokenDetails<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useContext<\/span><span class=\"p\">(<\/span><span class=\"nx\">Web3Context<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">router<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRouter<\/span><span class=\"p\">()<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">tokenId<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">router<\/span><span class=\"p\">.<\/span><span class=\"nx\">query<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">nft<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setNft<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">)<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">[<\/span><span class=\"nx\">loading<\/span><span class=\"p\">,<\/span> <span class=\"nx\">setLoading<\/span><span class=\"p\">]<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useState<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n\n  <span class=\"nx\">useEffect<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">simpleMint<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"nx\">address<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">loadNft<\/span><span class=\"p\">()<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[<\/span><span class=\"nx\">simpleMint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">address<\/span><span class=\"p\">])<\/span>\n\n  <span class=\"k\">async<\/span> <span class=\"kd\">function<\/span> <span class=\"nx\">loadNft<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">try<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">true<\/span><span class=\"p\">)<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">tokenURI<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">simpleMint<\/span><span class=\"p\">.<\/span><span class=\"nx\">tokenURI<\/span><span class=\"p\">(<\/span><span class=\"nx\">tokenId<\/span><span class=\"p\">)<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">metadata<\/span> <span class=\"o\">=<\/span> <span class=\"k\">await<\/span> <span class=\"nx\">axios<\/span><span class=\"p\">.<\/span><span class=\"kd\">get<\/span><span class=\"p\">(<\/span><span class=\"nx\">tokenURI<\/span><span class=\"p\">).<\/span><span class=\"nx\">then<\/span><span class=\"p\">((<\/span><span class=\"nx\">res<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">res<\/span><span class=\"p\">.<\/span><span class=\"nx\">data<\/span><span class=\"p\">)<\/span>\n\n      <span class=\"nx\">setNft<\/span><span class=\"p\">({<\/span> <span class=\"nx\">metadata<\/span><span class=\"p\">,<\/span> <span class=\"nx\">tokenId<\/span> <span class=\"p\">})<\/span>\n      <span class=\"nx\">setLoading<\/span><span class=\"p\">(<\/span><span class=\"kc\">false<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span> <span class=\"k\">catch<\/span> <span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nb\">window<\/span><span class=\"p\">.<\/span><span class=\"nx\">alert<\/span><span class=\"p\">(<\/span><span class=\"nx\">err<\/span><span class=\"p\">)<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">}<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">(<\/span>\n    <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">&lt;<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>Token: #<span class=\"si\">{<\/span><span class=\"nx\">tokenId<\/span><span class=\"si\">}<\/span> | Simple Mint<span class=\"p\">&lt;\/<\/span><span class=\"nt\">title<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">meta<\/span> <span class=\"na\">name<\/span><span class=\"p\">=<\/span><span class=\"s\">\"description\"<\/span> <span class=\"na\">content<\/span><span class=\"p\">=<\/span><span class=\"s\">\"NFT minting Dapp\"<\/span> <span class=\"p\">\/&gt;<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">link<\/span> <span class=\"na\">rel<\/span><span class=\"p\">=<\/span><span class=\"s\">\"icon\"<\/span> <span class=\"na\">href<\/span><span class=\"p\">=<\/span><span class=\"s\">\"\/favicon.ico\"<\/span> <span class=\"p\">\/&gt;<\/span>\n      <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Head<\/span><span class=\"p\">&gt;<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">loading<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">&lt;<\/span><span class=\"nc\">Loading<\/span> <span class=\"na\">text<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Loading\"<\/span> <span class=\"p\">\/&gt;<\/span><span class=\"si\">}<\/span>\n\n      <span class=\"si\">{<\/span><span class=\"nx\">nft<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n        <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"px-3 md:px-6\"<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">h1<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text-3xl font-bold\"<\/span><span class=\"p\">&gt;<\/span>Token: #<span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">tokenId<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">h1<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"grid grid-cols-1 gap-6 md:grid-cols-2\"<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"group relative h-96 rounded-md p-3 md:max-w-[100%]\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"relative h-96 rounded-md\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Image<\/span>\n                  <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"rounded-md\"<\/span>\n                  <span class=\"na\">layout<\/span><span class=\"p\">=<\/span><span class=\"s\">\"fill\"<\/span>\n                  <span class=\"na\">objectFit<\/span><span class=\"p\">=<\/span><span class=\"s\">\"cover\"<\/span>\n                  <span class=\"na\">quality<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"mi\">100<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">src<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">image<\/span><span class=\"si\">}<\/span>\n                  <span class=\"na\">alt<\/span><span class=\"p\">=<\/span><span class=\"s\">\"text\"<\/span>\n                <span class=\"p\">\/&gt;<\/span>\n              <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n\n            <span class=\"p\">&lt;<\/span><span class=\"nt\">div<\/span> <span class=\"na\">className<\/span><span class=\"p\">=<\/span><span class=\"s\">\"p-3\"<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* NFT Name *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">Details<\/span> <span class=\"na\">summary<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Name\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">name<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Details<\/span><span class=\"p\">&gt;<\/span>\n\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* NFT Description *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"p\">&lt;<\/span><span class=\"nc\">Details<\/span> <span class=\"na\">summary<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Description\"<\/span><span class=\"p\">&gt;<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span><span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">description<\/span><span class=\"si\">}<\/span><span class=\"p\">&lt;\/<\/span><span class=\"nt\">p<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Details<\/span><span class=\"p\">&gt;<\/span>\n\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* NFT Properties, if there are no properties don't display *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">filter<\/span><span class=\"p\">(<\/span>\n                <span class=\"p\">(<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text<\/span><span class=\"dl\">'<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">number<\/span><span class=\"dl\">'<\/span>\n              <span class=\"p\">).<\/span><span class=\"nx\">length<\/span> <span class=\"o\">!==<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Details<\/span> <span class=\"na\">summary<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Properties\"<\/span> <span class=\"na\">isGrid<\/span><span class=\"p\">&gt;<\/span>\n                  <span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">attributes<\/span>\n                    <span class=\"p\">.<\/span><span class=\"nx\">filter<\/span><span class=\"p\">(<\/span>\n                      <span class=\"p\">(<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n                        <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">text<\/span><span class=\"dl\">'<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">number<\/span><span class=\"dl\">'<\/span>\n                    <span class=\"p\">)<\/span>\n                    <span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n                      <span class=\"p\">&lt;<\/span><span class=\"nc\">DetailTile<\/span> <span class=\"na\">title<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">displayType<\/span><span class=\"si\">}<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n                    <span class=\"p\">))<\/span><span class=\"si\">}<\/span>\n                <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Details<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n\n              <span class=\"si\">{<\/span><span class=\"cm\">\/* NFT Boosts, if there are no boosts don't display *\/<\/span><span class=\"si\">}<\/span>\n              <span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">attributes<\/span><span class=\"p\">.<\/span><span class=\"nx\">filter<\/span><span class=\"p\">(<\/span>\n                <span class=\"p\">(<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n                  <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_percentage<\/span><span class=\"dl\">'<\/span> <span class=\"o\">||<\/span>\n                  <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_number<\/span><span class=\"dl\">'<\/span>\n              <span class=\"p\">).<\/span><span class=\"nx\">length<\/span> <span class=\"o\">!==<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"p\">(<\/span>\n                <span class=\"p\">&lt;<\/span><span class=\"nc\">Details<\/span> <span class=\"na\">summary<\/span><span class=\"p\">=<\/span><span class=\"s\">\"Boosts\"<\/span> <span class=\"na\">isGrid<\/span><span class=\"p\">&gt;<\/span>\n                  <span class=\"si\">{<\/span><span class=\"nx\">nft<\/span><span class=\"p\">.<\/span><span class=\"nx\">metadata<\/span><span class=\"p\">.<\/span><span class=\"nx\">attributes<\/span>\n                    <span class=\"p\">.<\/span><span class=\"nx\">filter<\/span><span class=\"p\">(<\/span>\n                      <span class=\"p\">(<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span>\n                        <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_percentage<\/span><span class=\"dl\">'<\/span> <span class=\"o\">||<\/span>\n                        <span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">traitType<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">boost_number<\/span><span class=\"dl\">'<\/span>\n                    <span class=\"p\">)<\/span>\n                    <span class=\"p\">.<\/span><span class=\"nx\">map<\/span><span class=\"p\">((<\/span><span class=\"nx\">attr<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">(<\/span>\n                      <span class=\"p\">&lt;<\/span><span class=\"nc\">DetailTile<\/span> <span class=\"na\">title<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">displayType<\/span><span class=\"si\">}<\/span> <span class=\"na\">value<\/span><span class=\"p\">=<\/span><span class=\"si\">{<\/span><span class=\"nx\">attr<\/span><span class=\"p\">.<\/span><span class=\"nx\">value<\/span><span class=\"si\">}<\/span> <span class=\"p\">\/&gt;<\/span>\n                    <span class=\"p\">))<\/span><span class=\"si\">}<\/span>\n                <span class=\"p\">&lt;\/<\/span><span class=\"nc\">Details<\/span><span class=\"p\">&gt;<\/span>\n              <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n            <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n          <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n        <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n      <span class=\"p\">)<\/span><span class=\"si\">}<\/span>\n    <span class=\"p\">&lt;\/<\/span><span class=\"nt\">div<\/span><span class=\"p\">&gt;<\/span>\n  <span class=\"p\">)<\/span>\n<span class=\"p\">}<\/span>\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>And that's all we needed to do with the front end.<\/p>\n\n<h2>\n  \n  \n  Deploy\n<\/h2>\n\n<p>To deploy from the terminal\/console, open the <code>scripts\/deploy.js<\/code> file, this file will be run by Brownie ETH to deploy the contract.<br>\n<\/p>\n\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight python\"><code><span class=\"kn\">from<\/span> <span class=\"nn\">brownie<\/span> <span class=\"kn\">import<\/span> <span class=\"n\">SimpleMint<\/span><span class=\"p\">,<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">,<\/span> <span class=\"n\">network<\/span>\n\n<span class=\"k\">def<\/span> <span class=\"nf\">main<\/span><span class=\"p\">():<\/span>\n    <span class=\"c1\"># requires brownie account to have been created\n<\/span>    <span class=\"k\">if<\/span> <span class=\"n\">network<\/span><span class=\"p\">.<\/span><span class=\"n\">show_active<\/span><span class=\"p\">()<\/span><span class=\"o\">==<\/span><span class=\"s\">'development'<\/span><span class=\"p\">:<\/span>\n        <span class=\"c1\"># add these accounts to metamask by importing private key\n<\/span>        <span class=\"n\">owner<\/span> <span class=\"o\">=<\/span> <span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]<\/span>\n        <span class=\"n\">SimpleMint<\/span><span class=\"p\">.<\/span><span class=\"n\">deploy<\/span><span class=\"p\">({<\/span><span class=\"s\">'from'<\/span><span class=\"p\">:<\/span><span class=\"n\">accounts<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"p\">]})<\/span>\n\n<\/code><\/pre>\n\n<\/div>\n\n\n\n<p>After this, you can run <code>brownie run deploy<\/code> to deploy your Simple Mint smart contract, <strong>be sure to run Ganache before running this command and to change the smart contract address in the _app.js file in the front-end.<\/strong><\/p>\n\n<p>That's all you needed to deploy the simple mint program to a local blockchain, there are many tutorials on how to deploy to an actual blockchain, so if you want to do that feel free to try it out.<\/p>\n\n<p>Thanks for reading, if you have any questions let me know in the comments.<\/p>\n\n","category":["solidity","nextjs","tailwindcss","dapp"]}]}}