Nous avons, jusqu'à présent, vu plusieurs modificateurs de fonction. Il n'est pas forcément évident de se rappeler de tous, nous allons donc les revoir rapidement :
private veut dire que la fonction ne peut être appelée que par les autres fonctions à l'intérieur du contrat; internal est comme private mais en plus, elle peut être appelée par les contrats qui héritent de celui-ci; avec external, la fonction ne peut être appelée que depuis l'extérieur du contrat; et enfin avec public, elle peut être appelée depuis n'importe où, à l'intérieur et à l'extérieur.view nous indique qu'en exécutant cette fonction, aucune donnée ne saura sauvegardée/modifiée. pure nous indique que non seulement aucune donnée ne saura sauvée sur la BlockChain, mais qu'en plus aucune donnée de la BlockChain ne sera lue. Ces 2 fonctions ne coûtent pas de gas si elles sont appelées depuis l'extérieur du contrat (mais elle coûtent du gas si elles sont appelées intérieurement par une autre fonction).onlyOwner et aboveLevel par exemple. Nous avons pu déterminer des logiques personnalisés pour ceux-ci, afin de choisir de quelles manières ils affectent une fonction.On peut aussi ajouter plusieurs modificateurs à la définition d'une fonction :
function test() external view onlyOwner anotherModifier {/* ... */ }
Dans ce chapitre, nous allons voir un nouveau modificateur de fonction : payable.
payableUne des choses qui rend Solidity et Ethereum vraiment cool est le modificateur payable, une fonction payable est une fonction spéciale qui peut recevoir des Ether.
Réfléchissons une minute. Quand vous faites un appel à une fonction API sur un serveur normal, vous ne pouvez pas envoyer des dollars US en même temps - pas plus que des Bitcoin.
Mais en Ethereum, puisque la monnaie (Ether), les données (charge utile de la transaction) et le code du contrat lui-même sont directement sur Ethereum, il est possible pour vous d'appeler une fonction et de payer le contrat en même temps.
Cela permet un fonctionnement vraiment intéressant, comme demander un certain paiement au contrat pour pouvoir exécuter une fonction.
contract OnlineStore {
function buySomething() external payable {
// Vérifie que 0.001 ether a bien été envoyé avec l'appel de la fonction :require(msg.value == 0.001 ether);
// Si c'est le cas, transférer l'article digital au demandeur de la fonction :
transferThing(msg.sender);
}
}
Ici, msg.value est la façon de voir combien d'Ether ont été envoyés au contrat, et ether est une unité intégrée.
Quelqu'un va appeler la fonction depuis web3.js (depuis l'interface utilisateur JavaScript de la DApp) de cette manière là :
// En supposant que `OnlineStore` pointe vers le contrat Ethereum :OnlineStore.buySomething({from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001)})
On remarque le champs value (valeur), où l'appel de la fonction Javascript indique combien d'ether envoyer (0.001). Si vous imaginez la transaction comme une enveloppe, et les paramètres que vous envoyez à l'appel de la fonction comme étant la lettre que vous mettez à l'intérieur, alors ajouter value revient au même que d'ajouter du cash à l'intérieur de l'enveloppe - la lettre et l'argent vont être donné au même moment au destinataire.
Remarque : Si une fonction n'est pas marquée payable et que vous essayez de lui envoyer des Ether, la fonction rejettera votre transaction.
uint levelUpFee = 0.001 ether;
modifier aboveLevel(uint _level, uint _zombieId) {
require(zombies[_zombieId].level >= _level);
_;
}
function levelUp(uint _zombieId) external payable {
require(msg.value == levelUpFee);
zombies[_zombieId].level++;
}