<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SoxZz5</title>
    <description>The latest articles on DEV Community by SoxZz5 (@soxzz5).</description>
    <link>https://dev.to/soxzz5</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F786618%2Ffca9bd2d-a4e2-44cb-bb9f-070baa9f2ec1.png</url>
      <title>DEV Community: SoxZz5</title>
      <link>https://dev.to/soxzz5</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/soxzz5"/>
    <language>en</language>
    <item>
      <title>Solidity, smart contracts et IPFS</title>
      <dc:creator>SoxZz5</dc:creator>
      <pubDate>Thu, 05 May 2022 09:14:01 +0000</pubDate>
      <link>https://dev.to/younup/solidity-smart-contracts-et-ipfs-5h2o</link>
      <guid>https://dev.to/younup/solidity-smart-contracts-et-ipfs-5h2o</guid>
      <description>&lt;h1&gt;
  
  
  Solidity, contrat et IPFS
&lt;/h1&gt;

&lt;p&gt;Dans ce chapitre nous allons voir le langage Solidity permettant l'écriture de smart contract sur la blockchain &lt;a href="https://ethereum.org/fr/"&gt;ETH&lt;/a&gt; et plus largement toutes les blockchains compatible &lt;a href="https://ethereum.org/en/developers/docs/evm/"&gt;EVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nous verrons aussi la réalisation d'un environnement de dev, puis l'implémentation d'un contrat avec Remix, puis nous aborderons l'utilisation d'IPFS afin de décentraliser les ressources vers lesquelles pointent nos tokens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Rappel sur les smart contracts&lt;/li&gt;
&lt;li&gt;
Solidity POO pour smart contract

&lt;ul&gt;
&lt;li&gt;
L'environnement de dev

&lt;ul&gt;
&lt;li&gt;Ganache-CLI&lt;/li&gt;
&lt;li&gt;VSCode/Remix&lt;/li&gt;
&lt;li&gt;Truffle&lt;/li&gt;
&lt;li&gt;Jest/Chai&lt;/li&gt;
&lt;li&gt;Metamask&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Notre premier smart contract ERC721

&lt;ul&gt;
&lt;li&gt;
Contrat du token

&lt;ul&gt;
&lt;li&gt;Base du contrat et standard ERC721&lt;/li&gt;
&lt;li&gt;Réalisation du contrat NFT avec IPFS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Chainlink Price Feed pour un prix en temps réel&lt;/li&gt;
&lt;li&gt;
Réalisation d'un Minter portant des limitations

&lt;ul&gt;
&lt;li&gt;Liaison du Minter avec Price Feed&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Réalisation d'une factory pour déployer

&lt;ul&gt;
&lt;li&gt;Déploiement testnet et test avec Remix&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Gestion de la ressource avec IPFS

&lt;ul&gt;
&lt;li&gt;IPFS c'est quoi ?&lt;/li&gt;
&lt;li&gt;Comment ça marche ?&lt;/li&gt;
&lt;li&gt;Le rôle d'IPFS avec les NFT&lt;/li&gt;
&lt;li&gt;Uploader vos metadata sur IPFS&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Finalité du chapitre&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Rappel sur les smart contracts &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7lcOUh6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/whatisnft.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7lcOUh6_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/whatisnft.jpg" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Un smart contract est un programme qui contrôle des actifs numériques, ce contrat intelligent vient convertir un accord entre deux parties en code informatique&lt;/p&gt;

&lt;p&gt;Il fige les règles de cet accord entre plusieurs parties dans la blockchain tout en assurant le transfert d'un actif, à l'instar des contrats légaux traditionnel, lorsque les conditions définies par le contrat se vérifient&lt;/p&gt;



&lt;p&gt;Ce type de contrat peut s'appliquer à de multiples domaines :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Les assurances&lt;/li&gt;
&lt;li&gt;L'immobilier&lt;/li&gt;
&lt;li&gt;Les supply chains (UPS,La poste...)&lt;/li&gt;
&lt;li&gt;La finance&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Les smart contract ne permettent pas uniquement d'automatiser les accords, ils les restreignent dans leurs actions.&lt;br&gt;
Ce genre de contrat tant à se développer dans les domaines nécessitant par exemple d'assurer le respect de la conformité.&lt;/p&gt;

&lt;p&gt;On peut "tout" créer avec un smart contract à l'image d'un langage comme le C# cependant le coût d'exécution et lui pris en compte lors de l'utilisation d'une fonction du code.&lt;/p&gt;

&lt;p&gt;Il faudra donc optimiser son code au maximum afin de réduire au minimum les frais de transactions lorsque l'utilisateur contactera votre contrat&lt;/p&gt;
&lt;h2&gt;
  
  
  Solidity POO pour smart contract &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.soliditylang.org/en/v0.8.9/"&gt;Solidity&lt;/a&gt; est un langage de programmation orienté objet de haut niveau utilisé dans l'implémentation de smart contract sur diverses blockchains, et notamment Ethereum.&lt;/p&gt;

&lt;p&gt;C'est un langage de type statique conçu pour compilé le code Solidity en &lt;a href="https://fr.wikipedia.org/wiki/Bytecode"&gt;Bytecode&lt;/a&gt; afin que les contrats s'exécutent sur une &lt;a href="https://dev.toEthereum%20Virtual%20Machine"&gt;EVM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XUZOGFrO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/evm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XUZOGFrO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/evm.png" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solidity est disponible sur les blockchains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ethereum.org/en/"&gt;Ethereum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tendermint.com/"&gt;Tendermint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tron.network/"&gt;Tron&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://academy.binance.com/fr/articles/an-introduction-to-binance-smart-chain-bsc"&gt;Binance Smart Chain&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  L'environnement de dev &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;La blockchain peut paraître complexe et demande un environnement de développement très complet dans notre cas nous allons avoir besoin de plusieurs logiciels/librairies/IDE:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Ganache -&amp;gt; Permet de simuler un noeud ethereum en local&lt;/li&gt;
&lt;li&gt;
VSCode/Remix -&amp;gt; Un IDE local et un IDE en ligne&lt;/li&gt;
&lt;li&gt;
Truffle -&amp;gt; Un environnement de développement, un cadre de test et un pipeline d'actifs (js,css...)&lt;/li&gt;
&lt;li&gt;
Jest/Chai -&amp;gt; Librairie de test et d'assertion pour tester notre contrat ou notre DAPP&lt;/li&gt;
&lt;li&gt;
Metamask -&amp;gt; Un wallet de crypto monnaie permettant le test de notre blockchain local&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Ganache-CLI &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;La ganache, ou crème ganache, ... (ok je rigole)&lt;br&gt;
&lt;br&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6H8NPC_C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/ganache.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6H8NPC_C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/ganache.svg" width="198" height="305"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Ganache, est un outil utilisé pour simuler une blockchain en local afin de rapidement développer vos contrat sur la blockchain Ethereum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/trufflesuite/ganache"&gt;Github Ganache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.trufflesuite.com/docs/ganache/overview"&gt;Documentation Ganache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Il est utilisé tout au long du cycle de développement, il permet de développer, déployer et tester votre application dans un environnement sûr et déterministe.&lt;/p&gt;

&lt;p&gt;Nous l'utiliserons dans la partie 3 de cette suite d'article afin de déployer notre contrat sur testnet sans Remix.&lt;/p&gt;
&lt;h4&gt;
  
  
  VSCode/Remix &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Afin de développer facilement un contrat il est conseillé de d'abord le faire sur &lt;a href="https://remix-project.org/"&gt;Remix&lt;/a&gt; puis de l'ajouter au projet final sur &lt;a href="https://code.visualstudio.com/"&gt;VScode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pour utiliser VSCode je vous conseille d'installer l'extension portant la syntaxe Solidity dans les fichiers &lt;code&gt;.sol&lt;/code&gt; -&amp;gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=JuanBlanco.solidity"&gt;Solidity extension&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ijZpsOJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/remix.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ijZpsOJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/remix.png" width="230" height="219"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remix est un IDE en ligne qui permet de développer, déployer et administrer un smart contract pour les blockchains de type Ethereum.&lt;/p&gt;

&lt;p&gt;Remix embarque un compilateur de script Solidity et un réseau de test afin de déployer le contrat.&lt;/p&gt;

&lt;p&gt;Remix permet aussi d'avoir accès à une interface exposant les fonctions du contrat afin de tester ces fonctions.&lt;/p&gt;



&lt;p&gt;Il peut être utiliser en tant que plateforme d'apprentissage, il suffit pour cela de retrouver le contrat que vous voulez comprendre sur la blockchain par exemple:&lt;/p&gt;

&lt;p&gt;Le contrat utilisé pour générer ce NFT &lt;a href="https://www.sothebys.com/en/buy/auction/2021/natively-digital-a-curated-nft-sale-2/to-be-announced"&gt;Fade&lt;/a&gt; est trouvable facilement avec son adresse&lt;br&gt;
&lt;code&gt;0x62F5418d9Edbc13b7E07A15e095D7228cD9386c5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;en utilisant &lt;a href="https://blockscan.com"&gt;Blockscan&lt;/a&gt; on retrouve facilement le contrat utilisé pour Fade&lt;br&gt;
(&lt;a href="https://etherscan.io/address/0x62F5418d9Edbc13b7E07A15e095D7228cD9386c5#code#F1#L1"&gt;Lien du contrat&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;En copiant &lt;code&gt;Fade.sol&lt;/code&gt; dans Remix je vais donc pouvoir avoir accès à toutes les fonctions du contrat en local.&lt;br&gt;
On poura donc comprendre ce qu'il se passe derrière la fonction &lt;code&gt;tokenURI&lt;/code&gt; qui retourne un gradient différent à chaque fois.&lt;/p&gt;
&lt;h4&gt;
  
  
  Truffle &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RVf7HQzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/truffle.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RVf7HQzM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/truffle.svg" width="265" height="279"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Truffle est un framework de développement pour Ethereum qui a pour mission de rendre le développement blockchain normalement complexe accessible à tous.&lt;/p&gt;

&lt;p&gt;Truffle va permettre de créer des migrations afin de déployer nos contrats, mais aussi l'exécution des tests permettant de certifier la sécurité et la qualité de ceux-ci.&lt;/p&gt;

&lt;p&gt;Dans le monde centralisé lorsque j'exécute un script JS c'est l'hébergeur qui répercute le prix, dans le monde décentralisé lorsque j'exécute une transaction avec un smart contract (donc j'exécute le script ou une partie du script de ce smart contract) je paye les frais en rapport avec le coût des fonctions qui seront exécutées.&lt;/p&gt;
&lt;h4&gt;
  
  
  Jest/Chai &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://jestjs.io/fr/"&gt;Jest&lt;/a&gt; est un framework de test JS qui va nous permettre de tester notre contrat ainsi que notre Dapp&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.chaijs.com/"&gt;Chai&lt;/a&gt; est une librairie JS qui va nous permettre de réaliser des assertions, c'est-à-dire, à la suite d'un test de vérifier les valeurs retournées.&lt;/p&gt;

&lt;p&gt;Garder les en mémoire, Jest et Chai sont conseillés lors de l'utilisation de Truffle et Ganache pour l'éxécution des tests automatisés, mais aussi du déploiement automatique lors des tests.&lt;/p&gt;
&lt;h4&gt;
  
  
  Metamask &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://metamask.io/"&gt;Metamask&lt;/a&gt; est un wallet (porte-monnaie) numérique, il va nous permettre de stocker nos NFT ou autre Cryptos.&lt;/p&gt;

&lt;p&gt;Metamask va permettre la gestion des échanges sur la blockchain, l'affichage de votre solde.&lt;/p&gt;

&lt;p&gt;Il permet de se connecter au réseau local créer par Ganache afin de tester sa Dapp avant de la fournir au monde entier.&lt;/p&gt;
&lt;h2&gt;
  
  
  Notre premier smart contract ERC721 &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Afin de réaliser notre premier smart contract et de simplifier la partie développement nous allons utiliser uniquement &lt;a href="https://remix.ethereum.org"&gt;Remix&lt;/a&gt; dans cette partie.&lt;/p&gt;
&lt;h3&gt;
  
  
  Contrat du token &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Nous allons donc créer le premier NFT de Younup, pour ce faire dans Remix, créer un nouveau fichier nommé &lt;code&gt;YounupNFT.sol&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Base du contrat et standard ERC721 &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;On commence par importer les standards portés par OpenZeppelin et les indications utiles au compilateur:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import of ERC721 Enumerable standard
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import of Ownable standard
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/access/Ownable.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import of Strings standard
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@openzeppelin/contracts/utils/Strings.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Réalisation du contrat NFT avec IPFS &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Avant de commencer si vous voulez en apprendre plus sur IPFS et uploader votre première image de façon décentralisée rendez-vous au chapitre IPFS.&lt;/p&gt;

&lt;p&gt;On va ensuite définir le contrat:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;YounupNFT&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;ERC721Enumerable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Ownable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//uint256 variable could use Strings library, example: value.toString()
&lt;/span&gt;  &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;Strings&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;//Declare metadata of token
&lt;/span&gt;  &lt;span class="c1"&gt;// ipfsURI =&amp;gt; Internet Protocol File Storage URI
&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ipfsURI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// ipfsExt =&amp;gt; Extension like .json
&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ipfsExt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;_symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;_ipfsURI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;ERC721&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_symbol&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//Require is use to check the variable value, it will throw "No IPFS URI provided" if you don't pass it
&lt;/span&gt;    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ipfsURI&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"No IPFS URI provided"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// We allocate ipfsURI to the ipfsURI passed on contract deployment
&lt;/span&gt;    &lt;span class="n"&gt;ipfsURI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_ipfsURI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// This function return the metadata of a given token, here it will return our ipfsURI (json metadata)
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;tokenURI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"ERC721URIStorage: URI query for nonexistent token"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ipfsURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// This function is use to mint (obtain, buy...) a token, it will use _safeMint from ERC721 standard
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;onlyOwner&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;tokenId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;totalSupply&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;_safeMint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;recipient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tokenId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Chainlink Price Feed pour un prix en temps réel &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Nous voulons vendre notre NFT à un prix fixe en $, on va alors utiliser le principe de &lt;a href="https://docs.chain.link/docs/get-the-latest-price/"&gt;Price Feed&lt;/a&gt; de &lt;a href="https://docs.chain.link/"&gt;Chainlink&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le principe est simple à l'instant donnée où l'on veut mint le NFT le smart contract va faire appelle au Price feed pour nous fournir une conversion de $ en crypto, ici nous utiliserons le token Matic de &lt;a href="https://polygon.technology/"&gt;Polygon&lt;/a&gt; pour ses frais minimes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;YounupNFT-priceFeed.sol&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;//Import Chainlink aggregator to call datafeed with price
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;YounupNFTPriceFeed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Private and immutable aggregator for security concern
&lt;/span&gt;  &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;_aggregator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// We use feedAddress (address of the token) in the aggregator
&lt;/span&gt;  &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;feedAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_aggregator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AggregatorV3Interface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feedAddress&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Return last price of the token
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getLatestPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only price not commented, we need to pass 5 arg, but we don't need the others datas
&lt;/span&gt;        &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="cm"&gt;/*uint80 roundID*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="cm"&gt;/*uint startedAt*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="cm"&gt;/*uint timeStamp*/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="cm"&gt;/*uint80 answeredInRound*/&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_aggregator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latestRoundData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Return the price decimals (since not all token have the same decimal we need to know it)
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_aggregator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// We add another contract so we could just deploy this one and don't need to send the token adress in the constructor since it's fixed here
// Here we pass the data from the MATIC testnet or mainnet because our NFT will be on polygon (MATIC)
&lt;/span&gt;&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;PriceFeedMaticUSD&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;YounupNFTPriceFeed&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cm"&gt;/**
     * Network: Polygon
     * Aggregator: MATIC/USD
     * Address (mainnet): 0xAB594600376Ec9fD91F8e885dADF0CE036862dE0
     * Address (testnet): 0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada
     * From: https://docs.chain.link/docs/matic-addresses/
     */&lt;/span&gt;
  &lt;span class="k"&gt;constructor&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;YounupNFTPriceFeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xd0D5e3DB44DE05E9F294BB0a3bEEaF030DE24Ada&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Réalisation d'un Minter portant des limitations &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Afin d'appliquer des limites de mint à notre NFT, par exemple limité son émission ou encore le nombre de token autorisé par utilisateur nous allons créer ce que l'on appelle un Minter.&lt;br&gt;
C'est ce contrat qui sera le seul à avoir le droit d'appeler la fonction mint de notre contrat NFT via l'utilisation du principe &lt;code&gt;Ownable&lt;/code&gt;, en effet notre contrat Minter va déployer le contrat du NFT et sera donc Owner.&lt;br&gt;
Tout d'abord nous allons définir la structure des paramètres d'entrée du contrat.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;YounupNFT-minter.sol&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"./YounupNFT-priceFeed.sol"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"./YounupNFT.sol"&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Parameters&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;chainCurrencyDecimals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Decimal of the token use
&lt;/span&gt;    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;presalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// First sale price in USD
&lt;/span&gt;    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Seconde sale price in USD
&lt;/span&gt;    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Max token mintable
&lt;/span&gt;    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;maxMint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Max mint by user
&lt;/span&gt;    &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Token is the YounupNFT token
&lt;/span&gt;    &lt;span class="n"&gt;YouNFTupPriceFeed&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Our created pricefeed contract
&lt;/span&gt;    &lt;span class="n"&gt;Periods&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// We will use periods to know when it's first or second sales
&lt;/span&gt;    &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="n"&gt;teamAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This is the team wallet that will receive all funds
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Token name ex: Ethereum
&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Token symbol ex: ETH
&lt;/span&gt;  &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ipfsURI&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Token IPFS Uri
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Periods&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// timestamp use for start and end private sale
&lt;/span&gt;  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;startPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;endPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// timestamp use for start and end of public sale
&lt;/span&gt;  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;startPublicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;endPublicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maintenant que nous avons définis les structures qui permettront d'utiliser et sécuriser notre contrat on peut écrire le reste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;YounupNFTMinter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We use it so we could now at wich state we are
&lt;/span&gt;  &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;waitingPeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// no mint possible
&lt;/span&gt;    &lt;span class="n"&gt;presalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Mint with the private sale price
&lt;/span&gt;    &lt;span class="n"&gt;publicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Mint with the public sale price
&lt;/span&gt;    &lt;span class="n"&gt;complete&lt;/span&gt; &lt;span class="c1"&gt;// All items are minted no more mint possible or you have outdated the endPublicSalePeriod
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="c1"&gt;// Chain info and team wallet
&lt;/span&gt;  &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;chainTokenDecimals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;teamAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;YounupNFT&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;//NFT max supply
&lt;/span&gt;  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;//NFT max mint per wallet
&lt;/span&gt;  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;maxMint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// NFT price in USD
&lt;/span&gt;  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;presalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="k"&gt;constant&lt;/span&gt; &lt;span class="n"&gt;ticketPriceDecimals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;//Periods
&lt;/span&gt;  &lt;span class="n"&gt;Periods&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;//Chainlink Price feed
&lt;/span&gt;  &lt;span class="n"&gt;YounupNFTPriceFeed&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;immutable&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Many test use to ensure that the periode are logics
&lt;/span&gt;      &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPresalePeriod&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid timestamp: startPresalePeriod"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endPresalePeriod&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid timestamp: endPresalePeriod"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPublicsalePeriod&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid timestamp: startPublicsalePeriod"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endPublicsalePeriod&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPublicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Invalid timestamp: endPlubicsalePeriod"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// We create the contract for the Token here
&lt;/span&gt;      &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;YounupNFT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ipfsURI&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;chainTokenDecimals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chainCurrencyDecimals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;presalePriceUSD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;presalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;maxSupply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;maxMint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;maxMint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;priceFeed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;periods&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="n"&gt;teamAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;teamAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Liaison du Minter avec Price Feed &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Notre contrat est maintenant initialiser mais il reste encore à mettre en place la possibilité de mint au prix voulu :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;mintNFT&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;external&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if contract is in state where you could mint
&lt;/span&gt;    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;presalePeriod&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"You can't mint it right now"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Get the mint price from priceFeed and ensure everything is ok with all limits and price passed
&lt;/span&gt;    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;entryPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getMintPrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;entryPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Not enough funds to mint YouNFTup. See getMintPrice()"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;totalSupply&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Too much NFT minted"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxMint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"You could mint only 1 YouNFTup"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Mint the token using the YounupNFT mint function
&lt;/span&gt;    &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// We also transfer all the fund sent to the contract to the team wallet
&lt;/span&gt;    &lt;span class="n"&gt;teamAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;this&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nb"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Function use to get the current state of the contract
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitingPeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endPresalePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;presalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;startPublicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitingPeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endPublicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;publicsalePeriod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Function use to get the mint price using priceFeed.getLatestPrice()
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getMintPrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;latestPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getLatestPrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;ticketPriceUSD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;presalePeriod&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ticketPriceUSD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;presalePriceUSD&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;latestPriceAdjusted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;uint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latestPrice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chainTokenDecimals&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="kt"&gt;uint&lt;/span&gt; &lt;span class="n"&gt;entryPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chainTokenDecimals&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;ticketPriceUSD&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;latestPriceAdjusted&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;ticketPriceDecimals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;entryPrice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Function to check if the contract is complete or no
&lt;/span&gt;  &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;isComplete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;getState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Il nous faut aussi mettre à jour le token car nous utilisons maintenant un minter, comme vu à la ligne suivante:&lt;br&gt;
&lt;code&gt;token = new YounupNFT(this, params.token.name, params.token.symbol, params.token.ipfsURI);&lt;/code&gt;&lt;br&gt;
this équivaut ici à &lt;code&gt;YounupNFTMinter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;YounupNFT.sol&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"./YounupNFTMinter.sol"&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;YouNFTupMinter&lt;/span&gt; &lt;span class="n"&gt;_minter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We keep info about the minter contract address
&lt;/span&gt;  &lt;span class="n"&gt;minter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_minter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La fonction mint étant &lt;code&gt;public onlyOwner&lt;/code&gt; seul le contrat Minter pourra minter un token YounupNFT&lt;/p&gt;

&lt;h3&gt;
  
  
  Réalisation d'une factory pour déployer &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Il ne nous reste plus qu'à déployer notre contrat pour simplifier cette partie je réalise une factory qui crée le constructeur plutôt que de le déclarer au déploiement sous forme de Tupple.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;YounupNFT-factory.sol&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="c1"&gt;// SPDX-License-Identifier: MIT
&lt;/span&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"./YouNFTup-minter.sol"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;YouNFTupFactory&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;YouNFTupMinter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;YouNFTupMinter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="n"&gt;chainCurrencyDecimals&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;presalePriceUSD&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;publicsalePriceUSD&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;maxSupply&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;maxMint&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"YouNFTup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"YNP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;ipfsURI&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"https://ipfs.io/ipfs/bafkreihmkaetjsqkb2cnzdkyhvpattzpj7duuqj4kfvtx3qfcitj2didbu"&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="n"&gt;priceFeed&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;PriceFeedMaticUSD&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="n"&gt;periods&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Periods&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="n"&gt;startPresalePeriod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;endPresalePeriod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;startPublicsalePeriod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;endPublicsalePeriod&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3600&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="n"&gt;teamAddress&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0xB677dd9Ae9217Fbb4E3d072b9F7F68947C2a4AA6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Déploiement testnet et test avec Remix &lt;a&gt;&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;Il ne reste plus qu'à compiler notre contrat et le déployer sur le réseau de test Matic.&lt;br&gt;
&lt;em&gt;(pour ajouter le réseau c'est &lt;a href="https://docs.polygon.technology/docs/develop/metamask/config-polygon-on-metamask/"&gt;ici&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Dans la partie "Solidity Compiler" de remix il faut choisir la version du compiler 0.8.12 puis compiler le contrat &lt;code&gt;YounupNFT-factory.sol&lt;/code&gt; qui importe tous les autres.&lt;/p&gt;

&lt;p&gt;Si vous avez bien installé Metamask et que vous avez ajouté le réseau &lt;code&gt;Matic Mumbai&lt;/code&gt; nous allons maintenant déployer notre contrat.&lt;/p&gt;

&lt;p&gt;Dans la partie "Deploy &amp;amp; run transactions" de Remix, il faut choisir pour Environment "Injected Web3", vous aurez alors une notification Metamask pensez à bien vérifier que vous êtes sur le testnet de polygon avant de déployer.&lt;/p&gt;

&lt;p&gt;On sélectionne ensuite le contrat &lt;code&gt;YounupNFT-factory&lt;/code&gt; puis on clique sur "Deploy", une transaction va alors apparaître sur votre Metamask si vous l'acceptez vous aller payer les fee de déploiement d'un contrat (sur testnet donc gratuit)&lt;/p&gt;

&lt;p&gt;Vous aurez alors accès à toutes les fonctions de votre contrat pour pouvoir le tester, vous pouvez finalement minter votre premier NFT et vérifier son existence via &lt;a href="https://testnets.opensea.io/"&gt;OpenSea Testnet&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yynNL5x2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/contract-func.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yynNL5x2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/contract-func.PNG" width="634" height="804"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Gestion de la ressource avec IPFS &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  IPFS c'est quoi ? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;IPFS ou InterPlanetary File System est un protocole P2P (pair à pair) Web3.0.&lt;br&gt;
Dans le monde du Web 2.0 nous stockons nos fichiers sur des serveurs centralisés, ici l'idée est de reposer sur la décentralisation et un réseau collaboratif afin d'héberger des fichiers.&lt;/p&gt;
&lt;h3&gt;
  
  
  Comment ça marche ? &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QdO7v7Xw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/ipfs-example.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QdO7v7Xw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/SoxZz5/NFT-tuto/master/doc/assets/ipfs-example.jpg" width="655" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L'objectif avec IPFS est de rendre le réseau :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;plus rapide&lt;/li&gt;
&lt;li&gt;plus sûr&lt;/li&gt;
&lt;li&gt;plus ouvert&lt;/li&gt;
&lt;li&gt;moins coûteux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dans un idéal de décentralisation il tend à prendre une place considérable façe au protocole HTTP&lt;/p&gt;
&lt;h3&gt;
  
  
  Le rôle d'IPFS avec les NFT &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Beaucoup de NFTs utilisent la blockchain pour leurs contrats mais n'utilisent aucun système décentralisé pour les ressources.&lt;/p&gt;

&lt;p&gt;En effet il est important de mettre en ligne les metadata et tous les assets qui permettront la génération du NFT sur un réseau décentralisé.&lt;/p&gt;

&lt;p&gt;L'objectif étant que le propriétaire du NFT soit en possession total de celui-ci sans que le créateur ne puisse détruire ou déplacer l'image par exemple.&lt;/p&gt;
&lt;h3&gt;
  
  
  Uploader vos metadata sur IPFS &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Afin de récupérer l'URL ipfs qui permettra de récupérer les infos de notre NFT dans le contrat.&lt;/p&gt;

&lt;p&gt;En partant de ce que nous allons développer ici :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      token: Token({
          name: "YouNFTup",
          symbol: "YNP",
          ipfsURI: "https://ipfs.io/ipfs/bafkreihmkaetjsqkb2cnzdkyhvpattzpj7duuqj4kfvtx3qfcitj2didbu"
      }),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;l'entièreté de cette tâche peut être automatisé par du script&lt;/em&gt;&lt;br&gt;
Nous allons utiliser &lt;a href="https://nft.storage"&gt;nft.storage&lt;/a&gt; pour ce faire, il existe aussi &lt;a href="https://www.pinata.cloud/"&gt;pinata&lt;/a&gt; :&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Créer un compte ou connectez-vous avec github&lt;/li&gt;
&lt;li&gt;Uploader votre image afin d'avoir un lien IPFS&lt;/li&gt;
&lt;li&gt;Rédiger le fichier &lt;code&gt;metadata.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Official Younup NFT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"external_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://younup.fr"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ipfs://your-image-link"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//example:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;https://ipfs.io/ipfs/bafkreigf&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;d&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;qgt&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;klvuxwr&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="err"&gt;d&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;yvkpjlrszlfhgpbphbdvwkzljivef&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="err"&gt;iu&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YouNFTup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"attributes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;You&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;can&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;many&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;attributes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;check&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;OpenSea&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;doc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Uploader le fichier de metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finalement, vous obtiendrez un fichier metada que vous pourrez lier à votre NFT.&lt;/p&gt;

&lt;p&gt;Example : &lt;a href="https://ipfs.io/ipfs/bafkreihmkaetjsqkb2cnzdkyhvpattzpj7duuqj4kfvtx3qfcitj2didbu"&gt;https://ipfs.io/ipfs/bafkreihmkaetjsqkb2cnzdkyhvpattzpj7duuqj4kfvtx3qfcitj2didbu&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalité du chapitre &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Le code : &lt;a href="https://github.com/SoxZz5/NFT-tuto/tree/master/project/contracts"&gt;https://github.com/SoxZz5/NFT-tuto/tree/master/project/contracts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Résultat: &lt;a href="https://testnets.opensea.io/assets/mumbai/0xe839ceaa7d410c7e957a97d970b8042b13a21c28/0"&gt;https://testnets.opensea.io/assets/mumbai/0xe839ceaa7d410c7e957a97d970b8042b13a21c28/0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Minter contract: &lt;a href="https://mumbai.polygonscan.com/address/0xc7cdcdfa7c724bd7148efb53a5774928f56dab46"&gt;https://mumbai.polygonscan.com/address/0xc7cdcdfa7c724bd7148efb53a5774928f56dab46&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NFT contract: &lt;a href="https://mumbai.polygonscan.com/address/0xe839ceaa7d410c7e957a97d970b8042b13a21c28"&gt;https://mumbai.polygonscan.com/address/0xe839ceaa7d410c7e957a97d970b8042b13a21c28&lt;/a&gt;&lt;/p&gt;

</description>
      <category>smartcontract</category>
      <category>erc721</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>C'est quoi un NFT ?</title>
      <dc:creator>SoxZz5</dc:creator>
      <pubDate>Thu, 06 Jan 2022 09:21:51 +0000</pubDate>
      <link>https://dev.to/younup/cest-quoi-un-nft--4k0f</link>
      <guid>https://dev.to/younup/cest-quoi-un-nft--4k0f</guid>
      <description>&lt;p&gt;Vous avez déjà entendu parler de blockchain ? De bitcoin ou encore d'Ethereum voir même de BNB ?&lt;br&gt;
Alors cet article est fait pour vous ; sinon je vous invite à voir la définition de la blockchain proposée :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.economie.gouv.fr/entreprises/blockchain-definition-avantage-utilisation-application" rel="noopener noreferrer"&gt;par le gouvernement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blockchainfrance.net/decouvrir-la-blockchain/c-est-quoi-la-blockchain/" rel="noopener noreferrer"&gt;par Blockchain France&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Définition
&lt;/h2&gt;

&lt;p&gt;Avant de parler de NFT, il faut aborder la notion de fongibilité pour en comprendre sa définition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fongible
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Se dit de choses qui se consomment par l'usage et qui peuvent être remplacées par des choses de même nature, de même qualité et de même quantité (par exemple denrées, argent comptant).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exemple: une pièce d'un euro est interchangeable avec une autre pièce d'un euro.&lt;/p&gt;

&lt;p&gt;Il en va de même des valeurs mobilières et, à plus forte raison, quand elles sont dématérialisées. En revanche, un appartement dans un immeuble ou une œuvre d'art sont des corps certains.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tne3fg8e5f3ywm8k1fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tne3fg8e5f3ywm8k1fd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  NFT
&lt;/h3&gt;

&lt;p&gt;Les NFT (Non Fungible Tokens ; en français, Tokens Non Fongibles), sont des actifs numériques, que l'on peut apparenter à des certificats d'authenticité, émis par une blockchain.&lt;/p&gt;

&lt;p&gt;Par exemple, dans le tableau ci-dessus expliquant le principe de fongibilité, les deux chats sont des NFT représentant chacun un &lt;a href="https://www.cryptokitties.co/" rel="noopener noreferrer"&gt;CryptoKitties&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Les NFT possèdent plusieurs propriétés :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unicité&lt;/strong&gt; : Elle permet de le définir à l'aide de métadonnées qui le décrivent et le distinguent des autres.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rareté&lt;/strong&gt; : Elle est établie par le fait que notre actif soit unique, un NFT ne peut être définie qu'une seule fois sur la blockchain. Cela crée donc un principe de rareté qui lui donne sa valeur. Exemple : Le bitcoin a sa rareté définie par son nombre de tokens limité, on peut définir autant de NFT que l'on veut dans une collection, mais chaque NFT de cette collection sera unique.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indivisibilité&lt;/strong&gt; : Il est impossible de diviser un NFT. Si on prend l'exemple d'un NFT représentant un billet de train, il n'est pas admissible qu'un utilisateur l'achète 10% de son prix.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pourquoi utiliser un NFT ?
&lt;/h2&gt;

&lt;p&gt;Là où les cryptomonnaies répondent au suivi d'actif, les NFT répondent au besoin d'un suivi d'actif unique.&lt;/p&gt;

&lt;p&gt;Les NFT trouvent tout leur sens dans l'économie numérique et couvrent un large spectre d'applications :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;des objets de collection,&lt;/li&gt;
&lt;li&gt;l'art physique et numérique,&lt;/li&gt;
&lt;li&gt;des objets de jeux vidéos (on peut citer CS:GO avec des skins allant à plusieurs dizaines de milliers d'euros, centralisés par Valve),&lt;/li&gt;
&lt;li&gt;des objets dans un monde virtuel (metaverse),&lt;/li&gt;
&lt;li&gt;des actifs physiques : maison, voiture, bateau, avion, etc.,&lt;/li&gt;
&lt;li&gt;l'identité et les dossier médicaux,&lt;/li&gt;
&lt;li&gt;l'assurance,&lt;/li&gt;
&lt;li&gt;l'héritage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;En bref, tout est imaginable à partir du moment où l'on veut représenter numériquement un actif afin qu'il soit unique tout en gardant les propriétés de la blockchain : non modifiable, non falsifiable, vérifiable. Cela permet donc la gestion d'un actif par un contrat figé avec des règles de transfert de cet actif.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonctionnement général et norme
&lt;/h2&gt;

&lt;p&gt;Un NFT est un token, il est donc relié à un smart contract.&lt;/p&gt;

&lt;p&gt;A la différence d'un contrat légal traditionnel, tel un contrat d'assurance, qui définit les règles d'un accord entre plusieurs parties, un smart contract va figer les règles dans la blockchain tout en assurant le transfert de l'actif concerné lorsque les conditions contractuelles se vérifient.&lt;/p&gt;

&lt;p&gt;On peut donc dire qu'un NFT est lié à un smart contract lui-même stocké dans une blockchain.&lt;/p&gt;

&lt;p&gt;Dans un objectif de normalisation &lt;a href="https://docs.openzeppelin.com/openzeppelin/" rel="noopener noreferrer"&gt;OpenZeppelin&lt;/a&gt; et la communauté ETH (&lt;a href="https://eips.ethereum.org/" rel="noopener noreferrer"&gt;Ethereum Improvement Proposals&lt;/a&gt;) ont proposé deux normes : &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc721" rel="noopener noreferrer"&gt;ERC-721&lt;/a&gt; et &lt;a href="https://docs.openzeppelin.com/contracts/4.x/erc1155" rel="noopener noreferrer"&gt;ERC-1155&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Là où les normes ERC-20 et ERC-777 répondent au besoin de suivi d'un token fongible, ERC-721 permet l'implémentation d'un token non fongible. ERC-1155 permet la gestion de tokens fongibles et non fongibles, mais nous n'aborderons pas cette norme dans cet article.&lt;/p&gt;

&lt;h2&gt;
  
  
  ERC-721
&lt;/h2&gt;

&lt;p&gt;Le smart contract ERC-721 est un ensemble de scripts permettant la gestion de plusieurs tokens de même type. Il contient:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;la liste des tokens créés,&lt;/li&gt;
&lt;li&gt;les propriétaires d'un ou plusieurs tokens,&lt;/li&gt;
&lt;li&gt;les personnes ayant droit sur la gestion d'un token,&lt;/li&gt;
&lt;li&gt;les données spécifiques à l'objet (NFT) représenté.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les interactions avec un NFT se font au moyen de transactions inscrites sur la blockchain. Il faut donc payer des &lt;em&gt;gas fee&lt;/em&gt; au réseau sur lequel le smart contract est exécuté. Les &lt;em&gt;gas fee&lt;/em&gt; sont des frais permettant le maintien du réseau. Pour en savoir plus, une définition est proposée par Cryptoast &lt;a href="https://cryptoast.fr/gas/" rel="noopener noreferrer"&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Propriétaire, opérateur et approbation
&lt;/h2&gt;

&lt;p&gt;Le propriétaire d'un token a pleins pouvoirs sur celui-ci. Il peut le détruire, le transférer ou encore déléguer son droit.&lt;/p&gt;

&lt;p&gt;La norme ERC-721 permet de définir un principe de délégation :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;via une adresse approuvée (0x08agea6486...)&lt;/li&gt;
&lt;li&gt;via un opérateur approuvé (ex: &lt;a href="https://www.binance.com/fr" rel="noopener noreferrer"&gt;Binance&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cela permet aux différentes personnes (adresses) d'avoir un droit permettant la gestion des tokens.Ce principe de délégation permet par exemple aux marketplaces de gérer les échanges de NFT entre propriétaires et acheteurs.&lt;/p&gt;

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

&lt;p&gt;Le NFT est un outil numérique qui va prendre de plus en plus de place dans le monde de demain.&lt;/p&gt;

&lt;p&gt;En effet, en dehors du secteur de l'art en pleine ébullition, aujourd'hui beaucoup d'entreprises prennent ce virage à l'image de Facebook qui va créer son propre &lt;a href="https://about.fb.com/news/2021/10/facebook-company-is-now-meta/" rel="noopener noreferrer"&gt;Metaverse&lt;/a&gt; (centralisé) ou encore &lt;a href="https://audius.co/" rel="noopener noreferrer"&gt;Audius&lt;/a&gt;, la société française qui se rêve en Spotify killer.&lt;/p&gt;

&lt;p&gt;Beaucoup de projets se basent sur le NFT en tant que preuve de confiance permettant de donner accès à des logiciels, des sites ou des applications aux détenteurs d'un NFT.&lt;/p&gt;

&lt;p&gt;Pour commencer à découvrir un nouveau monde, vous pouvez aller voir &lt;a href="https://evilkids.art" rel="noopener noreferrer"&gt;EvilKids&lt;/a&gt;, admirer &lt;a href="https://nfteyez.global/accounts/DPLQ2CsCpSd8ZHYZ9ukFsokE9cpVhgN6L9D6ihfetgqN/3dgallery" rel="noopener noreferrer"&gt;mon musée 3D&lt;/a&gt; ou encore mon projet &lt;a href="https://devpost.com/software/del-decentralized-lottery" rel="noopener noreferrer"&gt;SpaceTombo&lt;/a&gt;, vainqueur du &lt;a href="https://chainlink-fall-hackathon-2021.devpost.com/" rel="noopener noreferrer"&gt;Hackathon Chainlink - Winter 2021&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>nft</category>
      <category>solidity</category>
      <category>ethereum</category>
    </item>
  </channel>
</rss>
