Comment: créer un jeton sur le réseau PIRL

Partager cette publication

Partager sur facebook
Partager sur linkedin
Partager sur twitter
Partager sur email

La pièce

Nous allons créer un jeton numérique. Les jetons de l'écosystème Pirl peuvent représenter tout bien échangeable fongible: pièces de monnaie, points de fidélité, certificats d'or, reconnaissances de dette, objets en jeu, etc. Étant donné que tous les jetons implémentent certaines fonctionnalités de base de manière standard, cela signifie également que votre jeton sera instantanément compatible avec le portefeuille Pirl et tout autre client ou contrat utilisant les mêmes normes.

JETON VIABLE MINIMUM

Le contrat de jeton standard peut être assez complexe. Mais en substance, un jeton très basique se résume à ceci:

contract MyToken {/ * Ceci crée un tableau avec tous les soldes * / mapping (address => uint256) public balanceOf; / * Initialise le contrat avec les jetons de fourniture initiaux au créateur du contrat * / function MyToken (uint256 initialSupply) {balanceOf [msg.sender] = initialSupply; // Donne au créateur tous les jetons initiaux} / * Envoyer des pièces * / transfert de fonction (adresse _à, uint256 _valeur) {require (balanceOf [msg.sender]> = _value); // Vérifier si l'expéditeur a suffisamment de require (balanceOf [_to] + _value> = balanceOf [_to]); // Vérifier les débordements balanceOf [msg.sender] - = _value; // Soustraire de l'expéditeur balanceOf [_to] + = _value; // Ajoutez la même chose au destinataire}}

LE CODE

Mais si vous voulez simplement copier coller un code plus complet, utilisez ceci:

solidité du pragma ^ 0.4.16;

interface tokenRecipient {fonction receiveApproval (adresse _de, uint256 _valeur, adresse _token, octets _extraData) public; }

contrat TokenERC20 {
   // Variables publiques du token
   chaîne nom public;
   chaîne symbole public;
   uint8 décimales publiques = 18;
   // 18 décimales est la valeur par défaut fortement suggérée, évitez de la changer
   uint256 public totalSupply;

   // Cela crée un tableau avec tous les soldes
   mappage (adresse => uint256) public balanceOf;
   cartographie (adresse => cartographie (adresse => uint256)) allocation publique;

   // Cela génère un événement public sur la blockchain qui avertira les clients
   Transfert d'événement (adresse indexée à partir de, adresse indexée à, valeur uint256);

   // Cela informe les clients du montant brûlé
   événement Burn (adresse indexée à partir de, valeur uint256);

   /**
    * Fonction constructeur
    *
    * Initialise le contrat avec les jetons de fourniture initiaux au créateur du contrat
    */
   fonction TokenERC20 (
       uint256 initialSupply,
       string tokenName,
       jeton de chaîne
   ) Publique {
       totalSupply = initialSupply * 10 ** uint256 (décimales); // Mettre à jour l'approvisionnement total avec le montant décimal
       balanceOf [msg.sender] = totalSupply; // Donnez au créateur tous les jetons initiaux
       nom = tokenName; // Définir le nom à des fins d'affichage
       symbol = tokenSymbol; // Définit le symbole à des fins d'affichage
   }

   /**
    * Transfert interne, seul peut être appelé par ce contrat
    */
   fonction _transfer (adresse _de, adresse _à, uint _valeur) interne {
       // Empêche le transfert vers l'adresse 0x0. Utilisez plutôt burn ()
       require (_to! = 0x0);
       // Vérifier si l'expéditeur en a assez
       require (balanceOf [_from]> = _value);
       // Vérifier les débordements
       require (balanceOf [_to] + _value> balanceOf [_to]);
       // Enregistrez ceci pour une affirmation dans le futur
       uint previousBalances = balanceOf [_from] + balanceOf [_to];
       // Soustraire de l'expéditeur
       balanceOf [_from] - = _value;
       // Ajoutez le même au destinataire
       balanceOf [_to] + = _value;
       Transfert (_de, _à, _valeur);
       // Les assertions sont utilisées pour utiliser l'analyse statique pour trouver des bogues dans votre code. Ils ne devraient jamais échouer
       assert (balanceOf [_from] + balanceOf [_to] == previousBalances);
   }

   /**
    * Jetons de transfert
    *
    * Envoyez des jetons `_value` à` _to` depuis votre compte
    *
    * @param _to L'adresse du destinataire
    * @param _value le montant à envoyer
    */
   transfert de fonction (adresse _à, uint256 _valeur) public {
       _transfer (msg.sender, _to, _value);
   }

   /**
    * Transfert de jetons depuis une autre adresse
    *
    * Envoyez des jetons `_value` à` _to` au nom de `_from`
    *
    * @param _from L'adresse de l'expéditeur
    * @param _to L'adresse du destinataire
    * @param _value le montant à envoyer
    */
   function transferFrom (address _from, address _to, uint256 _value) renvoie public (bool success) {
       require (_value <= allocation [_from] [msg.sender]); // Indemnité de chèque
       allocation [_from] [msg.sender] - = _value;
       _transfer (_from, _to, _value);
       return true;
   }

   /**
    * Fixer une allocation pour une autre adresse
    *
    * Permet à `_spender` de ne pas dépenser plus de jetons` _value` en votre nom
    *
    * @param _spender L'adresse autorisée à dépenser
    * @param _value le montant maximum qu'ils peuvent dépenser
    */
   fonction approuver (adresse _spender, uint256 _value) public
       renvoie (bool success) {
       allocation [msg.sender] [_ spender] = _value;
       return true;
   }

   /**
    * Fixer une allocation pour une autre adresse et informer
    *
    * Permet à `_spender` de ne pas dépenser plus de jetons` _value` en votre nom, puis de cingler le contrat à ce sujet
    *
    * @param _spender L'adresse autorisée à dépenser
    * @param _value le montant maximum qu'ils peuvent dépenser
    * @param _extraData quelques informations supplémentaires à envoyer au contrat approuvé
    */
   function approveAndCall (address _spender, uint256 _value, bytes _extraData)
       Publique
       renvoie (bool success) {
       tokenRecipient spender = tokenRecipient (_spender);
       if (approve (_spender, _value)) {
           spender.receiveApproval (msg.sender, _value, this, _extraData);
           return true;
       }
   }

   /**
    * Détruisez les jetons
    *
    * Supprimer les jetons «_value» du système de manière irréversible
    *
    * @param _value le montant d'argent à brûler
    */
   fonction burn (uint256 _value) renvoie public (bool success) {
       require (balanceOf [msg.sender]> = _value); // Vérifier si l'expéditeur en a assez
       balanceOf [msg.sender] - = _value; // Soustraire de l'expéditeur
       totalSupply - = _value; // Met à jour totalSupply
       Burn (msg.sender, _value);
       return true;
   }

   /**
    * Détruisez les jetons d'un autre compte
    *
    * Supprimez les jetons `_value` du système de manière irréversible au nom de` _from`.
    *
    * @param _de l'adresse de l'expéditeur
    * @param _value le montant d'argent à brûler
    */
   La fonction burnFrom (address _from, uint256 _value) renvoie public (bool success) {
       require (balanceOf [_from]> = _value); // Vérifier si le solde ciblé est suffisant
       require (_value <= allocation [_from] [msg.sender]); // Indemnité de chèque
       balanceOf [_from] - = _value; // Soustraire du solde visé
       allocation [_from] [msg.sender] - = _value; // Soustraire de l'indemnité de l'expéditeur & #8217;
       totalSupply - = _value; // Mettre à jour totalSupply
       Burn (_from, _value);
       return true;
   }
}

Comprendre le code

Commençons donc par les bases de & #8217; Ouvrez l'application Wallet, accédez à l'onglet Contrats, puis Déployez le nouveau contrat. Dans le champ de texte Code source du contrat Solidity, saisissez le code ci-dessous:

contrat MyToken {
       / * Cela crée un tableau avec tous les soldes * /
       mappage (adresse => uint256) public balanceOf;
   }

Un mappage signifie un tableau associatif, où vous associez des adresses à des soldes. Les adresses sont au format Pirl hexadécimal de base, tandis que les soldes sont des entiers, allant de 0 à 115 quattuorvigintillion. Si vous ne savez pas combien coûte un quattuorvigintillion, c'est beaucoup de vigintillions de #8217; plus que tout ce pour quoi vous prévoyez d'utiliser vos jetons. Le mot-clé public signifie que cette variable sera accessible à tous sur la blockchain, ce qui signifie que tous les soldes sont publics (comme ils doivent l'être, pour que les clients les affichent).

Si vous publiez votre contrat tout de suite, cela fonctionnerait mais ne serait pas très utile: ce serait un contrat qui pourrait interroger le solde de votre pièce pour n'importe quelle adresse, mais comme vous n'avez jamais créé une seule pièce, chacune d'entre elles serait return 0. Nous allons donc créer quelques jetons au démarrage. Ajoutez ce code avant le dernier crochet de fermeture, juste sous la ligne de mappage ...

fonction MyToken () {
       balanceOf [msg.sender] = 21000000;
   }

Notez que la fonction MyToken porte le même nom que le contrat MyToken. Ceci est très important et si vous renommez l'un, vous devez également renommer l'autre: il s'agit d'une fonction de démarrage spéciale qui ne s'exécute qu'une seule fois et une seule fois lorsque le contrat est téléchargé pour la première fois sur le réseau. Cette fonction fixera le solde de msg.sender, l'utilisateur qui a déployé le contrat, avec un solde de 21 millions.

Le choix de 21 millions était plutôt arbitraire, et vous pouvez le changer pour tout ce que vous voulez dans le code, mais il y a une meilleure façon: au lieu de cela, fournissez-le comme paramètre pour la fonction, comme ceci:

function MyToken (uint256 initialSupply) public {
       balanceOf [msg.sender] = initialSupply;
   }

Jetez un œil à la colonne de droite à côté du contrat et vous verrez une liste déroulante, écrite choisissez un contrat. Sélectionnez le & #8220; MyToken & #8221; contrat et vous & #8217; vous verrez que maintenant il montre une section intitulée Paramètres du constructeur. Ce sont des paramètres modifiables pour votre jeton, vous pouvez donc réutiliser le même code et ne modifier ces variables qu'à l'avenir.

À l'heure actuelle, vous avez un contrat fonctionnel qui crée des soldes de jetons, mais comme il n'y a pas de fonction pour le déplacer, il ne reste que sur le même compte. Nous allons donc mettre cela en œuvre maintenant. Écrivez le code suivant avant le dernier crochet.

/ * Envoyer des pièces * /
   transfert de fonction (adresse _à, uint256 _valeur) {
       / * Ajouter et soustraire de nouveaux soldes * /
       balanceOf [msg.sender] - = _value;
       balanceOf [_to] + = _value;
   }

Il s'agit d'une fonction très simple: elle a un destinataire et une valeur comme paramètre et chaque fois que quelqu'un l'appelle, elle soustrait la _valeur de leur solde et l'ajoute au _au solde. Tout de suite là-bas & #8217; s un problème évident: que se passe-t-il si la personne veut envoyer plus qu'elle ne possède? Étant donné que nous ne voulons pas gérer la dette dans ce contrat particulier, nous allons simplement effectuer une vérification rapide et si l'expéditeur n'a pas suffisamment de fonds, l'exécution du contrat s'arrêtera simplement. Il est également nécessaire de vérifier les débordements, pour éviter d'avoir un nombre si grand qu'il redevienne nul.

Pour arrêter l'exécution d'un contrat en cours d'exécution, vous pouvez soit retourner, soit jeter. Le premier coûtera moins d'essence, mais cela peut être plus compliqué car tout changement apporté au contrat jusqu'à présent sera conservé. En revanche, & #8216; throw & #8217; annulera toute exécution du contrat, annulera toutes les modifications que la transaction aurait pu apporter et l'expéditeur perdra tout Pirl qu'il a envoyé pour le gaz. Mais comme le portefeuille peut détecter qu'un contrat sera lancé, il affiche toujours une alerte, empêchant ainsi tout Pirl d'être dépensé.

transfert de fonction (adresse _à, uint256 _valeur) {
       / * Vérifiez si l'expéditeur a l'équilibre et les débordements * /
       require (balanceOf [msg.sender]> = _value && balanceOf [_to] + _value> = balanceOf [_to]);

       / * Ajouter et soustraire de nouveaux soldes * /
       balanceOf [msg.sender] - = _value;
       balanceOf [_to] + = _value;
   }

 

Maintenant, tout ce qui manque, c'est d'avoir quelques informations de base sur le contrat. Dans un avenir proche, cela peut être géré par un registre de jetons, mais pour l'instant, nous les ajouterons directement au contrat:

chaîne nom public;
chaîne symbole public;
uint8 décimales publiques;

Et maintenant, nous mettons à jour la fonction constructeur pour permettre à toutes ces variables d'être configurées au début:

/ * Initialise le contrat avec les jetons de fourniture initiaux au créateur du contrat * /
   function MyToken (uint256 initialSupply, string tokenName, string tokenSymbol, uint8 decimalUnits) {
       balanceOf [msg.sender] = initialSupply; // Donnez au créateur tous les jetons initiaux
       nom = tokenName; // Définir le nom à des fins d'affichage
       symbol = tokenSymbol; // Définit le symbole à des fins d'affichage
       décimales = decimalUnits; // Nombre de décimales à des fins d'affichage
   }

Enfin, nous avons maintenant besoin de somPirling appelé Events. Ce sont des fonctions spéciales vides que vous appelez pour aider des clients comme le portefeuille Pirl à suivre les activités qui se déroulent dans le contrat. Les événements doivent commencer par une majuscule. Ajoutez cette ligne au début du contrat pour déclarer l'événement:

Transfert d'événement (adresse indexée à partir de, adresse indexée à, valeur uint256);
 

Et puis il vous suffit d'ajouter ces deux lignes à l'intérieur du & #8220; transfert & #8221; une fonction:

      / * Informez toute personne écoutant que ce transfert a eu lieu * /
       Transfert (msg.sender, _to, _value);

 

Et maintenant, votre jeton est prêt!

Vous avez remarqué les commentaires?

Quels sont ces commentaires @notice et @param, pourriez-vous demander? C'est & #8217; s Natspec une norme émergente pour une spécification en langage naturel, qui permet aux portefeuilles de montrer à l'utilisateur une description en langage naturel de ce que le contrat est sur le point de faire. Bien que cela ne soit pas actuellement pris en charge par de nombreux portefeuilles, cela changera à l'avenir, il est donc agréable d'être préparé.

Comment déployer

Si vous n'y êtes pas déjà & #8217; ouvrez le portefeuille Pirl, accédez à l'onglet contrats, puis cliquez sur & #8220; déployer le nouveau contrat & #8221 ;.

Maintenant, récupérez la source du jeton d'en haut et collez-la dans le champ & #8220; Solidity source & #8221 ;. Si le code se compile sans erreur, vous devriez voir un & #8220; choisir un contrat & #8221; liste déroulante à droite. Obtenez-le et sélectionnez & #8220; MyToken & #8221; Contrat. Dans la colonne de droite, vous verrez tous les paramètres dont vous avez besoin pour personnaliser votre propre jeton. Vous pouvez les modifier à votre guise.

Faites défiler jusqu'à la fin de la page et vous verrez une estimation du coût de calcul de ce contrat et vous pourrez sélectionner des frais sur le montant de Pirl que vous êtes prêt à payer pour cela. Tout excédent de Pirl que vous ne dépenserez pas vous sera retourné afin que vous puissiez laisser les paramètres par défaut si vous le souhaitez. Appuyez sur & #8220; déployer & #8221 ;, saisissez le mot de passe de votre compte et attendez quelques secondes que votre transaction soit récupérée.

Vous & #8217; serez redirigé vers la première page où vous pourrez voir votre transaction en attente de confirmations. Cliquez sur le compte et après pas plus d'une minute, vous devriez voir que votre compte montrera que vous avez 100% des partages que vous venez de créer. Pour en envoyer à quelques amis: sélectionnez & #8220; envoyer & #8221;, puis choisissez la devise que vous souhaitez envoyer (Pirl ou votre partage nouvellement créé), collez l'adresse de votre ami & #8217; sur l'adresse & #8220; à & #8221; champ et appuyez sur & #8220; envoyer & #8221 ;.

Si vous l'envoyez à un ami, il ne verra encore rien dans son portefeuille. En effet, le portefeuille ne suit que les jetons qu'il connaît et vous devez les ajouter manuellement. Accédez maintenant à & #8220; Contrats & #8221; onglet et vous devriez voir un lien vers votre contrat nouvellement créé. Cliquez dessus pour accéder à sa page. Puisqu'il s'agit d'une page de contrat très simple, il n'y a pas grand-chose à faire ici, cliquez simplement sur & #8220; copiez l'adresse & #8221; et collez l'adresse du contrat dans un éditeur de texte, vous en aurez besoin sous peu.

Pour ajouter un jeton à surveiller, accédez à la page des contrats, puis cliquez sur & #8220; Watch Token & #8221 ;. Une fenêtre contextuelle apparaîtra et il vous suffit de coller l'adresse du contrat. Le nom du jeton, le symbole et le nombre décimal doivent être remplis automatiquement, mais si ce n'est pas le cas, vous pouvez mettre tout ce que vous voulez (cela n'affectera que la façon dont il s'affiche sur votre portefeuille). Une fois que vous avez fait cela, vous & #8217; serez automatiquement montré tout solde que vous avez de ce jeton et vous & #8217; vous pourrez l'envoyer à quelqu'un d'autre.

Et maintenant, vous avez votre propre jeton de chiffrement! Les jetons en eux-mêmes peuvent être utiles comme échange de valeur sur les communautés locales, moyens de garder une trace des heures travaillées ou d'autres programmes de fidélité. Mais peut-on faire en sorte qu'une monnaie ait une valeur intrinsèque en la rendant utile?

Améliorez votre jeton

Vous pouvez déployer l'intégralité de votre jeton de chiffrement sans toucher à une ligne de code, mais la vraie magie se produit lorsque vous commencez à le personnaliser. Les sections suivantes seront des suggestions sur les fonctions que vous pouvez ajouter à votre jeton pour l'adapter davantage à vos besoins.

Plus de fonctions de base

Vous remarquerez qu'il existe d'autres fonctions dans votre contrat de jeton de base, comme approuver, envoyerFrom et autres. Ces fonctions sont là pour que votre jeton interagisse avec d'autres contrats: si vous voulez, par exemple, vendre des jetons à un échange décentralisé, il ne suffit pas de les envoyer à une adresse car l'échange ne sera pas au courant des nouveaux jetons ou de qui a envoyé eux, car les contrats ne sont pas en mesure de s'abonner aux événements uniquement pour des appels de fonction. Donc, pour les contrats, vous devez d'abord approuver le nombre de jetons qu'ils peuvent déplacer de votre compte, puis leur envoyer une requête ping pour leur faire savoir qu'ils doivent faire leur travail & #8211; ou effectuez les deux actions en une, avec approveAndCall.

Étant donné que bon nombre de ces fonctions doivent réimplémenter le transfert de jetons, il est logique de les remplacer par une fonction interne, qui ne peut être appelée que par le contrat lui-même:

/ * Transfert interne, ne peut être appelé que par ce contrat * /
   fonction _transfer (adresse _de, adresse _à, uint _valeur) interne {
       require (_to! = 0x0); // Empêche le transfert vers l'adresse 0x0. Utilisez plutôt burn ()
       require (balanceOf [_from]> = _value); // Vérifier si l'expéditeur en a assez
       require (balanceOf [_to] + _value> balanceOf [_to]); // Vérifier les débordements
       require (! freezAccount [_from]); // Vérifier si l'expéditeur est gelé
       require (! freezAccount [_to]); // Vérifier si le destinataire est gelé
       balanceOf [_from] - = _value; // Soustraire de l'expéditeur
       balanceOf [_to] + = _value; // Ajoutez le même au destinataire
       Transfert (_de, _à, _valeur);
   }

Maintenant, toutes vos fonctions qui entraînent le transfert de pièces peuvent effectuer leurs propres vérifications, puis appeler le transfert avec les paramètres corrects. Notez que cette fonction déplacera des pièces de n'importe quel compte vers un autre, sans exiger la permission de quiconque & #8217; pour cela: c'est & #8217; s pourquoi c'est & #8217; s une fonction interne, uniquement appelée par le contrat: si vous ajoutez une fonction qui l'appelle, faites assurez-vous qu'il vérifie correctement si l'appelant doit être autorisé à les déplacer.

Administrateur centralisé

Tous les dapps sont entièrement décentralisés par défaut, mais cela ne signifie pas qu'ils ne peuvent pas avoir une sorte de gestionnaire central, si vous le souhaitez. Peut-être que vous voulez pouvoir frapper plus de pièces, peut-être que vous voulez interdire à certaines personnes d'utiliser votre monnaie. Vous pouvez ajouter n'importe laquelle de ces fonctionnalités, mais le problème est que vous ne pouvez les ajouter qu'au début, de sorte que tous les détenteurs de jetons connaissent toujours exactement les règles du jeu avant de décider d'en posséder une.

Pour cela, vous avez besoin d'un contrôleur central des devises. Cela pourrait être un simple compte, mais pourrait également être un contrat et donc la décision de créer plus de jetons dépendra du contrat: s'il s'agit d'une organisation démocratique qui peut voter, ou peut-être juste un moyen de limiter le pouvoir du propriétaire du jeton.

Pour ce faire, nous allons apprendre une propriété très utile des contrats: l'héritage. L'héritage permet à un contrat d'acquérir les propriétés d'un contrat parent, sans avoir à les redéfinir toutes. Cela rend le code plus propre et plus facile à réutiliser. Ajoutez ce code à la première ligne de votre code, avant de contracter MyToken {.

appartenant au contrat {
       adresse au propriétaire public;

       propriété possédée () {
           propriétaire = msg.sender;
       }

       modificateur onlyOwner {
           require (msg.sender == owner);
           _;
       }

       transfert de fonction Propriétaire (adresse newOwner) onlyOwner {
           owner = newOwner;
       }
   }

Cela crée un contrat très basique qui ne fait rien d'autre que définir des fonctions génériques sur un contrat qui peut appartenir à & #8220; & #8221 ;. Maintenant, l'étape suivante consiste simplement à ajouter que le texte appartient à votre contrat:

 contrat MyToken appartient {
       / * le reste du contrat comme d'habitude * /

Cela signifie que toutes les fonctions de MyToken peuvent désormais accéder au propriétaire de la variable et au modificateur onlyOwner. Le contrat a également une fonction de transfert de propriété. Puisqu'il peut être intéressant de définir le propriétaire du contrat au démarrage, vous pouvez également l'ajouter à la fonction constructeur:

fonction MyToken (
       uint256 initialSupply,
       string tokenName,
       uint8 decimalUnits,
       token de chaîneSymbole,
       adresse centralMinter
       ) {
       if (centralMinter! = 0) owner = centralMinter;
   }

Monnaie centrale

Supposons que vous souhaitiez que la quantité de pièces en circulation change. C'est le cas lorsque vos jetons représentent réellement un actif hors blockchain (comme des certificats d'or ou des devises gouvernementales) et que vous souhaitez que l'inventaire virtuel reflète le réel. Cela pourrait également être le cas lorsque les détenteurs de devises s'attendent à un certain contrôle du prix du jeton et souhaitent émettre ou retirer des jetons de la circulation.

Tout d'abord, nous devons ajouter une variable pour stocker le totalSupply et l'assigner à notre fonction constructeur.

contrat MyToken {
       uint256 public totalSupply;

       fonction MyToken (& #8230;) {
           totalSupply = initialSupply;
           …
       }
       …
   }

Maintenant, ajoutons une nouvelle fonction à & #8217; qui permettra au propriétaire de créer de nouveaux jetons:

fonction mintToken (adresse cible, uint256 mintedAmount) onlyOwner {
       balanceOf [target] + = mintedAmount;
       totalSupply + = mintedAmount;
       Transfert (0, propriétaire, mintedAmount);
       Transfert (propriétaire, cible, mintedAmount);
   }

Remarquez le modificateur onlyOwner à la fin du nom de la fonction. Cela signifie que cette fonction sera réécrite lors de la compilation pour hériter du code du modificateur onlyOwner que nous avions défini auparavant. Le code de cette fonction & #8217; sera inséré là où il y a un soulignement sur la fonction de modification, ce qui signifie que cette fonction particulière ne peut être appelée que par le compte défini comme propriétaire. Ajoutez simplement cela à un contrat avec un modificateur de propriétaire et vous pourrez créer plus de pièces.

Gel des actifs

Selon votre cas d'utilisation, vous devrez peut-être avoir des obstacles réglementaires sur qui peut et ne peut pas utiliser vos jetons. Pour cela, vous pouvez ajouter un paramètre qui permet au propriétaire du contrat de geler ou de dégeler des actifs.

Ajoutez cette variable et travaillez n'importe où dans le contrat. Vous pouvez les placer n'importe où, mais pour de bonnes pratiques, nous vous recommandons de placer les mappages avec les autres mappages et les événements avec les autres événements.

mappage (adresse => bool) public freezAccount;
   événement FrozenFunds (adresse cible, bool figé);

   fonction freezeAccount (adresse cible, bool freeze) onlyOwner {
       freezAccount [target] = geler;
       FrozenFunds (cible, gel);
   }

Avec ce code, tous les comptes sont débloqués par défaut, mais le propriétaire peut définir l'un d'eux dans un état de gel en appelant Freeze Account. Malheureusement, le gel n'a aucun effet pratique car nous n'avons rien ajouté à la fonction de transfert. Nous changeons cela maintenant:

transfert de fonction (adresse _à, uint256 _valeur) {
       require (! freezAccount [msg.sender]);

Désormais, tout compte gelé aura toujours ses fonds intacts, mais ne pourra pas les déplacer. Tous les comptes sont débloqués par défaut jusqu'à ce que vous les geliez, mais vous pouvez facilement rétablir ce comportement dans une liste blanche où vous devez approuver manuellement chaque compte. Renommez simplement geléCompte en approuvéCompte et changez la dernière ligne en:

require (approuvéAccount [msg.sender]);

Vente et achat automatiques

Jusqu'à présent, vous avez utilisé l'utilité et la confiance pour évaluer votre jeton. Mais si vous le souhaitez, vous pouvez faire en sorte que la valeur du token & #8217; soit soutenue par Pirl (ou d'autres tokens) en créant un fonds qui les vend et les achète automatiquement à la valeur de marché.

Tout d'abord, fixons le prix d'achat et de vente de & #8217;

uint256 vente publiquePrix;
   uint256 public buyPrice;

   function setPrices (uint256 newSellPrice, uint256 newBuyPrice) onlyOwner {
       sellPrice = newSellPrice;
       buyPrice = newBuyPrice;
   }

Ceci est acceptable pour un prix qui ne change pas très souvent, car chaque nouveau changement de prix vous obligera à exécuter une transaction et à dépenser un peu de Pirl. Si vous souhaitez avoir un prix flottant constant, nous vous recommandons d'étudier les flux de données standard

L'étape suivante consiste à créer les fonctions d'achat et de vente:

fonction buy () retours payables (montant uint) {
       montant = msg.value / buyPrice; // calcule le montant
       require (balanceOf [this]> = amount); // vérifie s'il a assez à vendre
       balanceOf [msg.sender] + = montant; // ajoute le montant au solde de l'acheteur & #8217;
       balanceOf [this] - = montant; // soustrait le montant du solde du vendeur & #8217;
       Transfert (ce, msg.sender, montant); // exécute un événement reflétant le changement
       montant de retour; // termine la fonction et retourne
   }

   fonction sell (montant uint) retours (revenus uint) {
       require (balanceOf [msg.sender]> = montant); // vérifie si l'expéditeur a suffisamment à vendre
       balanceOf [this] + = montant; // ajoute le montant au solde du propriétaire & #8217;
       balanceOf [msg.sender] - = montant; // soustrait le montant du solde du vendeur #8217;
       revenus = montant * sellPrice;
       msg.sender.transfer (revenus); // envoie Pirl au vendeur: il est important de le faire en dernier pour éviter les attaques de récursivité
       Transfert (msg.sender, this, amount); // exécute un événement reflétant le changement
       revenus de retour; // termine la fonction et retourne
   }

Notez que cela ne créera pas de nouveaux jetons mais modifiera le solde du contrat. Le contrat peut détenir à la fois ses propres jetons et Pirl et le propriétaire du contrat, alors qu'il peut fixer des prix ou, dans certains cas, créer de nouveaux jetons (le cas échéant), il ne peut pas toucher les jetons de la banque et #8217; s ou Pirl. La seule façon dont ce contrat peut déplacer des fonds est de les vendre et de les acheter.

Remarque Acheter et vendre & #8220; prix & #8221; ne sont pas définis en Pirl, mais en wei la devise minimale du système (équivalent au centime en Euro et Dollar, ou au Satoshi en Bitcoin). Un Pirl est 1000000000000000000 wei. Donc, lorsque vous définissez les prix de votre jeton dans Pirl, ajoutez 18 zéros à la fin.

Lors de la création du contrat, envoyez-lui suffisamment de Pirl pour qu'il puisse racheter tous les jetons sur le marché, sinon votre contrat sera insolvable et vos utilisateurs ne pourront pas vendre leurs jetons.

Les exemples précédents décrivent bien sûr un contrat avec un seul acheteur et vendeur central, un contrat beaucoup plus intéressant permettrait un marché où n'importe qui peut proposer des prix différents, ou peut-être chargerait-il les prix directement d'une source externe.

Remplissage automatique

Chaque fois que vous effectuez une transaction sur Pirl, vous devez payer des frais au mineur du bloc qui calculera le résultat de votre contrat intelligent. Bien que cela puisse changer à l'avenir, pour le moment, les frais ne peuvent être payés que dans Pirl et donc tous les utilisateurs de vos jetons en ont besoin. Les jetons des comptes dont le solde est inférieur aux frais sont bloqués jusqu'à ce que le propriétaire puisse payer les frais nécessaires. Mais dans certains cas d'utilisation, vous ne voudrez peut-être pas que vos utilisateurs pensent à Pirl, à la blockchain ou à la façon d'obtenir Pirl, donc une approche possible consisterait à ce que votre pièce remplisse automatiquement le solde de l'utilisateur dès qu'il détecte que le solde est dangereusement bas.

Pour ce faire, vous devez d'abord créer une variable qui contiendra le seuil et une fonction pour le modifier.

uint minBalanceForAccounts;

   fonction setMinBalance (uint minimumBalanceInFinney) onlyOwner {
        minBalanceForAccounts = minimumBalanceInFinney * 1 finney;
   }

 

Ensuite, ajoutez cette ligne à la fonction de transfert pour que l'expéditeur soit remboursé:

  / * Envoyer des pièces * /
   transfert de fonction (adresse _à, uint256 _valeur) {
       …
       if (msg.sender.balance <minBalanceForAccounts)
           vendre ((minBalanceForAccounts & #8211; msg.sender.balance) / sellPrice);
   }

 

Vous pouvez également le modifier pour que les frais soient payés au destinataire par l'expéditeur:

  / * Envoyer des pièces * /
   transfert de fonction (adresse _à, uint256 _valeur) {
       …
       if (_to.balance            _to.send (sell ((minBalanceForAccounts & #8211; _to.balance) / sellPrice));
   }

Cela garantira qu'aucun compte recevant le jeton n'a moins que le Pirl nécessaire pour payer les frais.

Preuve de travail

Il existe plusieurs façons de lier votre offre de pièces à une formule mathématique. L'un des moyens les plus simples serait d'en faire un & #8220; minage fusionné & #8221; avec Pirl, ce qui signifie que toute personne qui trouve un bloc sur Pirl obtiendrait également une récompense de votre pièce, étant donné que quiconque appelle la fonction de récompense sur ce bloc. Vous pouvez le faire en utilisant le mot-clé spécial coinbase qui fait référence au mineur qui trouve le bloc.

function giveBlockReward () {
       balanceOf [block.coinbase] + = 1;
   }

Il est également possible d'ajouter une formule mathématique pour que toute personne capable de faire des mathématiques puisse gagner une récompense. Sur cet exemple suivant, vous devez calculer la racine cubique du défi actuel obtient un point et le droit de définir le prochain défi:

uint currentChallenge = 1; // Pouvez-vous déterminer la racine cubique de ce nombre?

   function récompenseMathGeniuses (uint answerToCurrentReward, uint nextChallenge) {
       require (answerToCurrentReward ** 3 == currentChallenge); // Si la réponse est incorrecte, ne continuez pas
       balanceOf [msg.sender] + = 1; // Récompense le joueur
       currentChallenge = nextChallenge; // Définissez le prochain défi
   }

Bien sûr, bien que le calcul des racines cubiques puisse être difficile à faire pour quelqu'un, il est très facile avec une calculatrice, ce jeu peut donc être facilement interrompu par un ordinateur. De plus, puisque le dernier gagnant peut choisir le prochain défi, il pourrait choisir un somPirling qu'il connaît et ne serait donc pas un jeu très équitable pour les autres joueurs. Il y a des tâches qui sont faciles pour les humains mais difficiles pour les ordinateurs, mais elles sont généralement très difficiles à coder dans des scripts simples comme ceux-ci. Au lieu de cela, un système plus juste devrait être très difficile à faire pour un ordinateur, mais ce n'est pas très difficile à vérifier pour un ordinateur. Un bon candidat serait de créer un défi de hachage où le challenger doit générer des hachages à partir de plusieurs nombres jusqu'à ce qu'il en trouve un qui soit inférieur à une difficulté donnée.

Ce processus a été proposé pour la première fois par Adam Back en 1997 Hashcash puis a été implémenté dans Bitcoin par Satoshi Nakamoto comme preuve de travail en 2008.

Si vous aimez le hachage comme une forme d'émission aléatoire de pièces, vous pouvez toujours créer votre propre monnaie basée sur Pirl qui a une preuve d'émission de travail:

bytes32 public currentChallenge; // La pièce commence par un défi
   uint public timeOfLastProof; // Variable pour garder une trace du moment où les récompenses ont été accordées
   uint difficulté publique = 10 ** 32; // La difficulté commence raisonnablement bas

   function proofOfWork (uint nonce) {
       octets8 n = octets8 (sha3 (nonce, currentChallenge)); // Génère un hachage aléatoire basé sur l'entrée
       require (n> = bytes8 (difficulté)); // Vérifiez s'il est & #8217; sous la difficulté

       uint timeSinceLastProof = (maintenant & #8211; timeOfLastProof); // Calcul du temps écoulé depuis la dernière récompense
       require (timeSinceLastProof> = 5 secondes); // Les récompenses ne peuvent pas être données trop rapidement
       balanceOf [msg.sender] + = timeSinceLastProof / 60 secondes; // La récompense du gagnant augmente de minute en minute

       difficulté = difficulté * 10 minutes / timeSinceLastProof + 1; // Ajuste la difficulté

       timeOfLastProof = maintenant; // Réinitialiser le compteur
       currentChallenge = sha3 (nonce, currentChallenge, block.blockhash (block.number & #8211; 1)); // Enregistrer un hachage qui sera utilisé comme prochaine preuve
   }

Modifiez également la fonction Constructor (celle qui porte le même nom que le contrat, qui est appelée lors du premier téléchargement) pour ajouter cette ligne, afin que le réglage de la difficulté ne devienne pas fou:

timeOfLastProof = maintenant;

Une fois le contrat en ligne, sélectionnez la fonction & #8220; Preuve de travail & #8221 ;, ajoutez votre numéro préféré dans le champ nonce et essayez de l'exécuter. Si la fenêtre de confirmation affiche un avertissement rouge indiquant & #8220; Les données ne peuvent & #8217; pas être exécutées & #8221; revenir en arrière et choisir un autre numéro jusqu'à ce que vous en trouviez un qui permette à la transaction d'aller de l'avant: ce processus est aléatoire. Si vous en trouvez un, vous recevrez 1 jeton pour chaque minute écoulée depuis la dernière récompense, puis la difficulté du défi sera ajustée à la hausse ou à la baisse pour viser une moyenne de 10 minutes par récompense.

Ce processus d'essayer de trouver le numéro qui vous donnera une récompense est ce qu'on appelle l'exploitation minière: si la difficulté augmente, il peut être très difficile de trouver un numéro porte-bonheur, mais il sera toujours facile de vérifier que vous en avez trouvé un.

Pièce améliorée

CODE COIN COMPLET
Si vous ajoutez toutes les options avancées, voici à quoi devrait ressembler le code final:

solidité du pragma ^ 0.4.16;

appartenant au contrat {
   adresse au propriétaire public;

   fonction propriété () public {
       propriétaire = msg.sender;
   }

   modificateur onlyOwner {
       require (msg.sender == owner);
       _;
   }

   function transferOwnership (address newOwner) onlyOwner public {
       owner = newOwner;
   }
}


solidité du pragma ^ 0.4.16;

appartenant au contrat {
   adresse au propriétaire public;

   fonction propriété () public {
       propriétaire = msg.sender;
   }

   modificateur onlyOwner {
       require (msg.sender == owner);
       _;
   }

   function transferOwnership (address newOwner) onlyOwner public {
       owner = newOwner;
   }
}

interface tokenRecipient {fonction receiveApproval (adresse _de, uint256 _valeur, adresse _token, octets _extraData) public; }

contrat TokenERC20 {
   // Variables publiques du token
   chaîne nom public;
   chaîne symbole public;
   uint8 décimales publiques = 18;
   // 18 décimales est la valeur par défaut fortement suggérée, évitez de la changer
   uint256 public totalSupply;

   // Cela crée un tableau avec tous les soldes
   mappage (adresse => uint256) public balanceOf;
   cartographie (adresse => cartographie (adresse => uint256)) allocation publique;

   // Cela génère un événement public sur la blockchain qui avertira les clients
   Transfert d'événement (adresse indexée à partir de, adresse indexée à, valeur uint256);

   // Cela informe les clients du montant brûlé
   événement Burn (adresse indexée à partir de, valeur uint256);

   /**
    * Fonction constructeur
    *
    * Initialise le contrat avec les jetons de fourniture initiaux au créateur du contrat
    */
   fonction TokenERC20 (
       uint256 initialSupply,
       string tokenName,
       jeton de chaîne
   ) Publique {
       totalSupply = initialSupply * 10 ** uint256 (décimales); // Mettre à jour l'approvisionnement total avec le montant décimal
       balanceOf [msg.sender] = totalSupply; // Donnez au créateur tous les jetons initiaux
       nom = tokenName; // Définir le nom à des fins d'affichage
       symbol = tokenSymbol; // Définit le symbole à des fins d'affichage
   }

   /**
    * Transfert interne, seul peut être appelé par ce contrat
    */
   fonction _transfer (adresse _de, adresse _à, uint _valeur) interne {
       // Empêche le transfert vers l'adresse 0x0. Utilisez plutôt burn ()
       require (_to! = 0x0);
       // Vérifier si l'expéditeur en a assez
       require (balanceOf [_from]> = _value);
       // Vérifier les débordements
       require (balanceOf [_to] + _value> balanceOf [_to]);
       // Enregistrez ceci pour une affirmation dans le futur
       uint previousBalances = balanceOf [_from] + balanceOf [_to];
       // Soustraire de l'expéditeur
       balanceOf [_from] - = _value;
       // Ajoutez le même au destinataire
       balanceOf [_to] + = _value;
       Transfert (_de, _à, _valeur);
       // Les assertions sont utilisées pour utiliser l'analyse statique pour trouver des bogues dans votre code. Ils ne devraient jamais échouer
       assert (balanceOf [_from] + balanceOf [_to] == previousBalances);
   }

   /**
    * Jetons de transfert
    *
    * Envoyez des jetons `_value` à` _to` depuis votre compte
    *
    * @param _to L'adresse du destinataire
    * @param _value le montant à envoyer
    */
   transfert de fonction (adresse _à, uint256 _valeur) public {
       _transfer (msg.sender, _to, _value);
   }

   /**
    * Transfert de jetons depuis une autre adresse
    *
    * Envoyez des jetons `_value` à` _to` au nom de `_from`
    *
    * @param _from L'adresse de l'expéditeur
    * @param _to L'adresse du destinataire
    * @param _value le montant à envoyer
    */
   function transferFrom (address _from, address _to, uint256 _value) renvoie public (bool success) {
       require (_value <= allocation [_from] [msg.sender]); // Indemnité de chèque
       allocation [_from] [msg.sender] - = _value;
       _transfer (_from, _to, _value);
       return true;
   }

   /**
    * Fixer une allocation pour une autre adresse
    *
    * Permet à `_spender` de ne pas dépenser plus de jetons` _value` en votre nom
    *
    * @param _spender L'adresse autorisée à dépenser
    * @param _value le montant maximum qu'ils peuvent dépenser
    */
   fonction approuver (adresse _spender, uint256 _value) public
       renvoie (bool success) {
       allocation [msg.sender] [_ spender] = _value;
       return true;
   }

   /**
    * Fixer une allocation pour une autre adresse et informer
    *
    * Permet à `_spender` de ne pas dépenser plus de jetons` _value` en votre nom, puis de cingler le contrat à ce sujet
    *
    * @param _spender L'adresse autorisée à dépenser
    * @param _value le montant maximum qu'ils peuvent dépenser
    * @param _extraData quelques informations supplémentaires à envoyer au contrat approuvé
    */
   function approveAndCall (address _spender, uint256 _value, bytes _extraData)
       Publique
       renvoie (bool success) {
       tokenRecipient spender = tokenRecipient (_spender);
       if (approve (_spender, _value)) {
           spender.receiveApproval (msg.sender, _value, this, _extraData);
           return true;
       }
   }

   /**
    * Détruisez les jetons
    *
    * Supprimer les jetons «_value» du système de manière irréversible
    *
    * @param _value le montant d'argent à brûler
    */
   fonction burn (uint256 _value) renvoie public (bool success) {
       require (balanceOf [msg.sender]> = _value); // Vérifier si l'expéditeur en a assez
       balanceOf [msg.sender] - = _value; // Soustraire de l'expéditeur
       totalSupply - = _value; // Met à jour totalSupply
       Burn (msg.sender, _value);
       return true;
   }

   /**
    * Détruisez les jetons d'un autre compte
    *
    * Supprimez les jetons `_value` du système de manière irréversible au nom de` _from`.
    *
    * @param _de l'adresse de l'expéditeur
    * @param _value le montant d'argent à brûler
    */
   La fonction burnFrom (address _from, uint256 _value) renvoie public (bool success) {
       require (balanceOf [_from]> = _value); // Vérifier si le solde ciblé est suffisant
       require (_value <= allocation [_from] [msg.sender]); // Indemnité de chèque
       balanceOf [_from] - = _value; // Soustraire du solde visé
       allocation [_from] [msg.sender] - = _value; // Soustraire de l'indemnité de l'expéditeur & #8217;
       totalSupply - = _value; // Mettre à jour totalSupply
       Burn (_from, _value);
       return true;
   }
}

/******************************************/
/ * JETON AVANCÉ COMMENCE ICI * /
/******************************************/

contrat MyAdvancedToken appartient, TokenERC20 {

   uint256 vente publiquePrix;
   uint256 public buyPrice;

   mappage (adresse => bool) public freezAccount;

   / * Cela génère un événement public sur la blockchain qui avertira les clients * /
   événement FrozenFunds (adresse cible, bool figé);

   / * Initialise le contrat avec les jetons de fourniture initiaux au créateur du contrat * /
   fonction MyAdvancedToken (
       uint256 initialSupply,
       string tokenName,
       jeton de chaîne
   ) TokenERC20 (initialSupply, tokenName, tokenSymbol) public {}

   / * Transfert interne, seul peut être appelé par ce contrat * /
   fonction _transfer (adresse _de, adresse _à, uint _valeur) interne {
       require (_to! = 0x0); // Empêche le transfert vers l'adresse 0x0. Utilisez plutôt burn ()
       require (balanceOf [_from]> = _value); // Vérifier si l'expéditeur en a assez
       require (balanceOf [_to] + _value> balanceOf [_to]); // Vérifier les débordements
       require (! freezAccount [_from]); // Vérifier si l'expéditeur est gelé
       require (! freezAccount [_to]); // Vérifier si le destinataire est gelé
       balanceOf [_from] - = _value; // Soustraire de l'expéditeur
       balanceOf [_to] + = _value; // Ajoutez le même au destinataire
       Transfert (_de, _à, _valeur);
   }

   /// @notice Créez des jetons `mintedAmount` et envoyez-les à` target`
   /// @param target Address pour recevoir les jetons
   /// @param mintedAmount le nombre de jetons qu'il recevra
   function mintToken (adresse cible, uint256 mintedAmount) onlyOwner public {
       balanceOf [target] + = mintedAmount;
       totalSupply + = mintedAmount;
       Transfert (0, this, mintedAmount);
       Transfert (this, target, mintedAmount);
   }

   /// @notice `geler? Empêcher | Autoriser `` la cible '' à envoyer et recevoir des jetons
   /// @param cible Adresse à figer
   /// @param freeze soit pour le figer soit non
   fonction freezeAccount (adresse cible, bool freeze) onlyOwner public {
       freezAccount [target] = geler;
       FrozenFunds (cible, gel);
   }

   /// @notice Autoriser les utilisateurs à acheter des jetons pour `newBuyPrice` Pirl et à vendre des jetons pour` newSellPrice` Pirl
   /// @param newSellPrice Prix que les utilisateurs peuvent vendre au contrat
   /// @param newBuyPrice Prix que les utilisateurs peuvent acheter à partir du contrat
   function setPrices (uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {
       sellPrice = newSellPrice;
       buyPrice = newBuyPrice;
   }

   /// @notice Achetez des jetons du contrat en envoyant Pirl
   fonction buy () payable public {
       uint amount = msg.value / buyPrice; // calcule le montant
       _transfer (this, msg.sender, amount); // effectue les transferts
   }

   /// @notice Vendez des jetons `montant 'au contrat
   /// @param montant montant des jetons à vendre
   fonction vendre (montant uint256) public {
       require (this.balance> = amount * sellPrice); // vérifie si le contrat a suffisamment de Pirl à acheter
       _transfer (msg.sender, this, amount); // effectue les transferts
       msg.sender.transfer (montant * prix de vente); // envoie Pirl au vendeur. Il est important de le faire en dernier pour éviter les attaques de récursivité
   }
}

Déployer

Faites défiler vers le bas et vous verrez le coût estimatif du déploiement. Si vous le souhaitez, vous pouvez modifier le curseur pour définir des frais moins élevés, mais si le prix est trop inférieur au taux moyen du marché, votre transaction peut prendre plus de temps à prendre. Cliquez sur Déployer et saisissez votre mot de passe. Après quelques secondes, vous & #8217; serez redirigé vers le tableau de bord et sous Dernières transactions, vous & #8217; verrez une ligne indiquant & #8220; création du contrat & #8221 ;. Attendez quelques secondes que quelqu'un choisisse votre transaction, puis vous verrez un rectangle bleu lent représentant le nombre d'autres nœuds qui ont vu votre transaction et les ont confirmés. Plus vous avez de confirmations, plus vous avez l'assurance que votre code a été déployé.

Cliquez sur le lien qui indique la page d'administration et vous serez le tableau de bord de banque centrale le plus simple au monde, où vous pourrez faire tout ce que vous voulez avec votre nouvelle monnaie créée.

Sur le côté gauche, sous Lire du contrat, vous avez toutes les options et fonctions que vous pouvez utiliser pour lire gratuitement les informations du contrat. Si votre jeton a un propriétaire, il affichera son adresse ici. Copiez cette adresse et collez-la dans Balance of et elle vous montrera le solde de n'importe quel compte (le solde est également affiché automatiquement sur toute page de compte qui a des jetons).

Sur le côté droit, sous Écrire dans le contrat, vous verrez toutes les fonctions que vous pouvez utiliser pour modifier ou changer la blockchain de quelque manière que ce soit. Ceux-ci coûteront du gaz. Si vous avez créé un contrat qui vous permet de frapper de nouvelles pièces, vous devriez avoir une fonction appelée & #8220; Mint Token & #8221 ;. Sélectionnez-le.

Sélectionnez l'adresse où ces nouvelles devises seront créées, puis le montant (si vous avez des décimales définies à 2, puis ajoutez 2 zéros après le montant, pour créer la quantité correcte). Sur Exécuter à partir de, sélectionnez le compte défini comme propriétaire, laissez le montant Pirl à zéro et appuyez sur Exécuter.

Après quelques confirmations, le solde du destinataire sera mis à jour pour refléter le nouveau montant. Mais votre portefeuille destinataire peut ne pas l'afficher automatiquement: pour être au courant des jetons personnalisés, le portefeuille doit les ajouter manuellement à une liste de surveillance. Copiez votre adresse de jeton (sur la page d'administration, appuyez sur copier l'adresse) et envoyez-la à votre destinataire. S'ils n'ont pas déjà #8217; t, ils doivent aller dans l'onglet contrats, appuyez sur Watch Token, puis ajoutez-y l'adresse. Le nom, les symboles et les nombres décimaux affichés peuvent être personnalisés par l'utilisateur final, surtout s'il a d'autres jetons avec un nom similaire (ou le même). L'icône principale n'est pas modifiable et les utilisateurs doivent y faire attention lors de l'envoi et de la réception de jetons pour s'assurer qu'ils traitent la vraie affaire et non un jeton de copie.

Utiliser votre pièce

Une fois que vous & #8217; avez déployé vos jetons, ils seront ajoutés à votre liste de jetons surveillés et le solde total sera affiché sur votre compte. Pour envoyer des jetons, allez simplement dans l'onglet Envoyer et sélectionnez un compte qui contient des jetons. Les jetons du compte seront répertoriés juste sous Pirl. Sélectionnez-les, puis saisissez le nombre de jetons que vous souhaitez envoyer.

Si vous souhaitez ajouter le jeton de quelqu'un d'autre & #8217 ;, accédez simplement à l'onglet Contrats et cliquez sur Regarder le jeton. Par exemple, pour ajouter le jeton Pirl Vortex à votre liste de surveillance, ajoutez simplement l'adresse 0x0489A975393A1cD0330740040141D702C35180cb

Maintenant quoi?

Vous venez d'apprendre comment utiliser Pirl pour émettre un jeton, qui peut représenter tout ce que vous voulez. Mais que pouvez-vous faire avec les jetons? Vous pouvez utiliser, par exemple, les jetons pour représenter une action dans une entreprise ou vous pouvez utiliser un comité central pour voter sur le moment d'émettre de nouvelles pièces pour contrôler l'inflation. Vous pouvez également les utiliser pour collecter des fonds pour une cause, via une vente publique. Que construirez-vous ensuite?

Matériel de référence: ethereum.org


Abonnez-vous à notre newsletter

Recevez des mises à jour et apprenez des meilleurs

Plus à explorer

fr_FRFrançais
en_USEnglish nl_NLNederlands tr_TRTürkçe es_ESEspañol pt_PTPortuguês ru_RUРусский ko_KR한국어 zh_CN简体中文 hi_INहिन्दी fr_FRFrançais