Nous allons voir comment créer un Token (Smart Contract) sur
la Binance Smart Chain (BSC) et le déployer afin de
permettre à tout le monde de le trader.
Nous partons
du principe que vous connaissez déjà les principes
de la crypto monnaie, que vous en avez déjà
acheté, et que savez comment fonctionne les portefeuilles
(wallets).
Les Smart Contracts sont des programmes qui
contrôlent directement des actifs numériques. Ce sont
ces programmes qui, une fois
« inséré » dans la blockchain,
vont définir comment ces actifs vont être
gérés.
Une fois que le programme est
ajouté à la blockchain, il n’est plus
modifiable et il est impossible de le supprimer.
Nous
utilisons ici les mécanismes de Smart Contract de la
Blockchain de Binance, la BSC (sur le réseau
BEP20).
Nous avons choisi la BSC car les frais de gaz sont
très faibles.
Il est possible de faire la même
chose sur la Blockchain Ethereum (ERC20) mais chaque transactions
peut représenter plusieurs dizaines d’euros contre
quelques fractions de centimes sur la BSC.
Ajouter le réseau BSC au wallet MetaMask
Pour valider les transactions sur la BSC il vous faudra un
portefeuille (wallet) relié au réseau BEP20.
Pour
cela nous allons installer MetaMask, lui ajouter du BNB (la
monnaie nécessaire pour payer les frais de transaction), et
le relier au réseau BEP20.
Vous pouvez l’installer sur votre téléphone ou
bien sur votre PC (préférable pour suivre cet
article).
https://metamask.io/download
Notez bien votre seed phrase (la clé privée) et
gardez la en lieux sûr.
Ne la
transférez jamais à un tiers.
C’est cette clé qui vous permettra de
réinstaller votre portefeuille plus tard.
Une fois
installée il vous faudra aller dans la configuration de
l’extension et ajouter le réseau BSC.
Cliquez
sur la barre du milieux qui contient le nom du réseau puis
sur « RPC personnalisé ».
Complétez le formulaire suivant :
Pour le réseau principal (Main Net) :
Network
Name : Binance Smart Chain
New RPC URL :
https://bsc-dataseed.binance.org/
ChainID
: 56
Symbol :
BNB
Block Explorer URL : https://bscscan.com
Puis le réseau de test (Testnet) :
https://docs.binance.org/smart-chain/developer/rpc.html
Network
Name : Binance Smart Chain Testnet
New RPC
URL :
https://data-seed-prebsc-2-s1.binance.org:8545/
ChainID
: 97
Symbol :
BNB
Block Explorer URL :
https://testnet.bscscan.com
En règle générale, pour tester votre contrat,
vous commencerez par le publier dans le testnet.
Pour cela il
vous faudra alimenter votre wallet avec du BNB de test
(heureusement gratuit).
Il vous suffit de vous rendre sur la page suivante : https://testnet.binance.org/faucet-smart
Puis de renseigner l’adresse de votre portefeuille.
Votre adresse se trouve ici :
Vous renseignez votre adresse puis sélectionnez 1 BNB dans la liste ‘Give me BNB’.
Votre compte sera automatiquement crédité.
Création de votre Smart Contract
On a vu précédemment qu’un Smart Contract
était un programme inséré dans la blockchain.
Pour le réseau BEP20 (BSC), le langage de programmation
utilisé est le Solidity.
Vous trouverez la
documentation complète ici :
https://solidity-fr.readthedocs.io/fr/latest/
Honnêtement, ce n’est pas très compliqué. Il suffit de RTFM, comme un peu tous les langages. Il est aussi accessible que JavaScript.
Pour rédiger notre programme, le compiler et le publier, nous allons le faire directement en ligne sur le site https://remix.ethereum.org/
Tout vas se faire directement depuis ce site.
Nous
allons créer un Token appelé le
« PartiTech Token » avec le symbole
« PTECH ».
1 – On crée notre fichier
On prendra bien soin de nommer notre fichier du nom de notre projet.
2 – L’entête de notre fichier
Très importante, c’est elle qui va définir la
version du compilateur utilisé et par conséquent la
version du langage.
Dans notre cas, nous allons utiliser la
dernière version :
pragma solidity ^0.8.4;
3 – Le corp de notre programme
Nous créons ensuite notre contrat via la déclaration
« contract » que nous nommerons de la
même manière que notre fichier (ce qui est un peu
plus propre).
A noter que vous pouvez déclarer
autant de contrats que vous le souhaitez dans un même
fichier.
pragma solidity ^0.8.4;
contract PTECH
{
}
4 – Définition de notre contrat
Nous allons devoir définir quelques paramètres de
notre contrat.
Son nom, le nombre de token, et son
symbole.
Arrêtons nous un instant sur la syntaxe que
nous allons utiliser. Nous devons déclarer des variables.
Comme dans la plupart des langages, elle sont typées
(int, string, bool etc) et ont une portée (publique ou
privée).
Dans la blockchains tout est publique. Donc
ne vous méprenez pas sur la notion de privée,
c’est une portée d’accès de la valeur
mais il est toujours possible d’y accéder.
pragma solidity ^0.8.4;
contract PTECH
{
uint private totalSupply = 1 000 000 000 000;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
}
Notre contrat aura 1k Milliards de tokens disponibles et
s’appellera le « Parti Tech Token »
avec un symbole « PTECH ».
(Franchement,
on a pas longtemps hésité entre PTECH et
PTT…)
Donc comme vous le voyez, déclarer une chaîne est tout simple :
Type+Portée+Nom = valeur;
Mais ce n’est pas tout.
Nous voulons ajouter des
décimales à notre token de sorte que les traders
puissent en acheter des fractions. Nous allons donc
spécifier le nombre de décimales.
pragma solidity ^0.8.4;
contract PTECH
{
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
}
Notez bien notre nouvelle variable
« decimals » et la modification faite sur la
variable « totalSupply ».
18
décimal, puis un nombre de token de 1 000 000 000 000 * 10
** 18
La double * permet de donner la puissance du nombre,
et on multiplie le nombre de token par 10 car d’un point de
vue du portefeuille pour afficher un token, il lui faut 10
unités. Donc nous devons multiplier le nombre réel
de token par 10 puissance 18 pour les décimales.
5 – Ajouter le mapping des tokens aux adresses
A ce stade, notre contrat ne sait même pas qu’il a pour logique d’affecter des token à des utilisateurs. Pour le moment, il sait juste qu’il a un nombre de token total dont la répartition lui est totalement inconnue.
Pour cela, nous allons ajouter un mapping des adresses des gens (wallets) à la répartition des tokens que nous allons appeler balance (comme une balance en comptabilité).
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
}
En faisant ça, on affecte à notre objet
« balances » l’ensemble des adresses
qui vont interagir avec notre contrat. Nous pourrons plus tard
manipuler « balance » pour ajouter ou
supprimer des tokens aux adresses.
Pour faire simple, on
va mapper un index à une valeur. L’index sera
l’adresse d’un utilisateur et la valeur les token
qu’il aura acheté ou gagné (oui parce
qu’on est pas forcé d’acheter le token, on peut
en faire gagner aussi, à l’image des token
déflationnistes).
6 – Le constructeur
Le constructeur est à l’image d’un « constructor » dans les autres langages. C’est une fonction qui sera exécutée qu’une seule fois dans la vie du programme. Et comme on a vu que le programme était exécuté à vie, sans possibilité de le mettre à jour, le constructeur sera vraiment exécuté qu’une seule fois.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
constructor(){
balances[msg.sender]=totalSupply;
}
}
Faisons le point sur ce que l’on vient d’ajouter.
Notre constructeur ne prend pas d’argument. Dedans, nous
affectons l’ensemble des tokens à un indice
précis. Notre indice, c’est une adresse.
Pour
bien comprendre le mécanisme, à chaque interaction
entre un utilisateur et notre programme, la blockchains va envoyer
des messages. Un message en entrée, un message en retour.
Lorsque le contrat est publié, celui qui le publie est
le détenteur du contrat, c’est nous.
Donc le
message en entrée qui est représenté par
l’objet « msg » contient en
paramètre « sender » notre
adresse.
Nous affectons donc à notre adresse
l’ensemble des tokens disponibles.
On pourrait
très bien faire une répartition sur plusieurs
adresses. Par exemple, créer un portefeuille mort (dead
wallet) et y affecter dès la création du contrat un
pourcentage de nos tokens.
On pourrais aussi créer un
portefeuille pour le marketing, pour les devs et leurs
répartir des tokens qu’ils utiliseront plus tard,
lorsqu’il y aura de la liquidité, pour se
rémunérer ou financer une action marketing.
7 – Fonction pour lire la balance d’un utilisateur
Nous devons
maintenant produire une série de fonctionnalités
à notre programme qui permettront de gérer les
fonctions basiques de notre contrat.
La première est de
récupérer la balance de l’utilisateur.
En
gros, lorsque vous ouvrez votre wallet, la première chose
qu’il va faire est d’envoyer une requête vers le
contrat pour récupérer votre solde.
Et le
protocole va exécuter une fonction définie par le
protocole qui s’appelle
« balanceOf() ». Cette fonction aura
toujours comme argument l’adresse du messager.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
}
Wait. Prends 2 secondes pour analyser la syntaxe de notre
fonction.
function balanceOf(address user) public
view returns (uint)
En gros qu’est-ce
que l’on vient de faire ? On spécifie le type de
retour que va produire notre fonction. Tout simplement.
Avec
une portée publique ou privée et un retour de type
integer (uint). Et chose importante, la propriété
n’est que lisible (view, en gros lecture seule).
Ensuite,
on voit que notre fonction prend en entrée une variable
user qui n’est autre qu’une adresse et que l’on
retourne ensuite la valeur affectée pour l’indice
correspondant à notre adresse dans notre tableau
« balances ».
8 – Le transfert de tokens aux utilisateurs
Il nous faut maintenant définir l’interaction entre
chaque transaction.
Lorsqu’un utilisateur va acheter
notre token sur une maketplace il va nous envoyer une demande de
transfert. A la réception nous devrons affecter le nombre
de tokens à notre utilisateur.
Si nous voulions
faire un système comme le DOGE coin, qui crée des
tokens à chaque transaction, nous pourrions le faire ici.
De même, si nous voulions faire un mécanisme de Burn,
nous pourrions le faire ici aussi.
Comme vous le voyez,
tous ces termes qui circulent autour des contrats sont en
réalité très simples à
implémenter.
Une règle mathématique toute
bête.
Ça ne sera pas notre cas ici. Restons
simple.
Donc à chaque transaction le protocole de la
blockchain va nous envoyer un message qui appellera la fonction
« transfer() » qui contiendra
l’adresse de l’utilisateur.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
function transfer(address to, uint value) public view returns (uint)
{
require(balanceOf(msg.sender)>=value, "Solde est insuffisant");
}
}
Globalement, une transaction c’est un transfert d’une
valeur d’une adresse à une autre. Donc si le
détenteur A veux transférer un token à un
détenteur B, il faut impérativement que A
possède au moins 1 token.
Pour cela nous allons
utiliser l’instruction « requier »,
qui permet de valider une condition. Si la condition
échoue, alors le processus est arrêté, et une
erreur est renvoyée au protocole qui se charge de le
transmettre à l’utilisateur.
Donc ce que
l’on fait, c’est récupérer
l’adresse de l’utilisateur et appeler notre fonction
« balanceOf » qui nous retourne le solde
pour l’adresse donnée et valider que le nombre de
tokens à transférer est disponible dans la balance
du donneur d’ordre.
Si le solde est insuffisant, on
arrête la transaction.
A noter que l’objet msg
est global et disponible à tout moment dans chaque function
au moment d’une transaction.
En fonction du résultat, on incrémente le solde du destinataire et on décrémente le solde du donneur d’ordre.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
function transfer(address to, uint value) public view returns (uint)
{
require(balanceOf(msg.sender)>=value, "Solde est insuffisant");
balances[to]+=value;
balances[msg.sender]-=value;
}
}
Une fois que la balance est faite, on va écrire dans la
blockchain. Pour cela nous allons émettre un
événement « Transfer ».
Un
peu comme en JS on pourrait faire un fire event dans le DOM.
Pour invoquer un évènement, on utilise le
mot-clé « emit », et pour
déclarer l’évènement, on utilise le
mot-clé « event ».
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
function transfer(address to, uint value) public returns (bool)
{
require(balanceOf(msg.sender)>=value, "Solde insuffisant");
balances[to]+=value;
balances[msg.sender]-=value;
emit Transfer(msg.sender, to, value);
return true;
}
}
Donc une fois validée, on envoit un ordre de transfert du donneur d’ordre « msg.sender » vers le destinataire « to » pour une valeur « value ».
8 -La délégation de transfert
La délégation de transfert donne la
possibilité à un tiers de faire des transferts
à la place du détenteur du contrat. C’est
exactement ce que fait la finance décentralisée
(DEFI).
Donc ce qu’il se passe c’est que l’on
autorise le contrat à effectuer des transferts à
notre place ce qui permet ensuite au contrat de passer des ordres
depuis l’adresse du détenteur vers l’adresse du
destinataire.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
mapping (address => mapping (address=>uint)) public allowance;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
function transfer(address to, uint value) public returns (bool)
{
require(balanceOf(msg.sender)>=value, "Solde insuffisant");
balances[to]+=value;
balances[msg.sender]-=value;
emit Transfer(msg.sender, to, value);
return true;
}
function approve(address spender, uint value) public returns (bool)
{
allowance[msg.sender][spender]=value;
emit Approval(msg.sender, spender, value);
return true;
}
}
Je ne vais pas revenir sur les concepts que nous avons vus plus
haut.
On crée un mapping d’adresses qui contient
lui même un mapping d’adresses. En gros un tableau
à 3 dimensions.
On crée une fonction
« approve » qui va affecter à notre
mapping d’adresses une valeur. Ce qui va permettre de dire
au système que cette adresse a le droit de dépenser
en notre nom tel nombre de tokens.
On rajoute une fonction « TransferFrom » qui, lorsque l’ordre sera un ordre délégué, va vérifier la balance et vérifier la délégation. Si la balance est suffisante, et que la délégation est suffisante aussi, alors on calcule les balances de notre tableau « balances » et on émet un évènement transfert pour écrire dans la blockchain.
pragma solidity ^0.8.4;
contract PTECH
{
mapping (address => uint) public balances;
mapping (address => mapping (address=>uint)) public allowance;
uint private totalSupply = 1 000 000 000 000 * 10 ** 18;
string public name = "Parti Tech Token";
string public symbol = "PTECH";
uint public decimals = 18;
event Transfer(address indexed from, address indexed to, uint value);
event Approval(address indexed owner, address indexed spender, uint value);
constructor(){
balances[msg.sender]=totalSupply;
}
function balanceOf(address user) public view returns (uint)
{
return balances[user];
}
function transfer(address to, uint value) public returns (bool)
{
require(balanceOf(msg.sender)>=value, "Solde insuffisant");
balances[to]+=value;
balances[msg.sender]-=value;
emit Transfer(msg.sender, to, value);
return true;
}
function TransferFrom(address from, address to, uint value) public returns (bool)
{
require(balanceOf(from)>=value, "Solde insuffisant");
require(allowance[from][msg.sender]>=value, "Délégation insuffisante");
balances[to]+=value;
balances[from]-=value;
emit Transfer(from, to, value);
return true;
}
function approve(address spender, uint value) public returns (bool)
{
allowance[msg.sender][spender]=value;
emit Approval(msg.sender, spender, value);
return true;
}
}
Déploiement du contrat dans la Blockchain
Pour lé déploiement, on reste dans notre éditeur du site https://remix.ethereum.org/
On va maintenant compiler notre contrat en vérifiant bien la
version du compilateur et le type de langage.
On cochera
« Hide warning » pour ne pas se polluer avec
des messages non bloquants.
Il faut ensuite injecter web3 dans votre projet. En gros, cela va
lier votre portefeuille MetaMask à votre contrat.
On
positionnera au préalable MetaMask sur le réseau
TestNet.
Ensuite on se positionne dans l’onglet déploiement, on
injecte « Web3 », MetaMask s’ouvre et
nous demande de valider quel compte nous voulons utiliser.
On valide.
Le numéro de notre compte est directement remplis dans
l’interface.
On clique sur « Déploy » et
MétaMask nous demande de valider la transaction.
Le
déploiement va nous coûter 0.0088 BNB. Une broutille.
Sans compter que sur le TestNet, on peut se créditer des
BNB de tests 😉
Et on confirme.
On a la petite coche verte, tout est bon !
On vérifie
la transaction dans MétaMask.
On clique sur le lien pour vérifier le déploiement sur bscscan.com
Voilà, notre contrat est créé.
Nous
verrons dans un prochain chapitre comment y ajouter de la
liquidité afin de permettre le tradding dans les
différentes places de marché.
Création d’une paire et pool de liquidité
Pour que votre contrat soit en capacité d’être
traidé, il faudra créer une paire avec un autre
token et y ajouter de la liquidité.
Par exemple, faire
une paire PTECH/BNB. On y créera un pool d’une
fraction ou de la totalité de nos token disponibles, et on
lui affectera une valeur de départ.
250 000 000 000
token pour 33BNB (soit à peut pret 10 000$ au cours
d’aujourd’hui) serait une bonne valeur de
départ.
Pour cela nous allons aller sur pancakeswap
: https://pancakeswap.finance
On choisi
« Liquidity » dans le menu
« Trade »
Ensuite on selectionne l’onglet « Liquidity » et on clique sur « + Add Liquidity »
Il faut impérativement connecter son wallet au site, si nous souhaitons que le site créé notre pool.
Une fois connecté, le site nous indique nos pools. Pour le
moment, nous n’en avons pas.
On clique sur « + Add liquidity »
Et on ajoute notre token. Dans la liste, on clique sur Manage token
Puis dans l’onglet token on ajoute l’adresse de notre contrat :
Une fois le contrat importé, on le selectionne :
Et on choisis la deuxieme devise a
« coupler » avec notre contrat.
Contrat/devise ou devise/Contrat, c’est comme vous le
souhaitez.
On clique sur « Enable » et on laisse travailler Metamask qui va vous demander d’authoriser les transactions necessaire à la création du pool.
Vous ne devriez pas tarder a le voir listé dans les nouveaux contrats disponibles. Par exemple sur https://poocoin.app/ape
Une fois que votre pool est créé
Si vous cet article vous a été utile,
n’hésitez pas a me faire un petit dont de quelques
milliards 😉
Mon adresse :
0x3637fCa571aeA47DBC90f61c38629dd92a742315
Je listerais ci-dessous les généreux donateurs avec l’adresse du pool sur un exchange pour pouvoir le trader :
Montant | Token | Addresse exchange |