Unités et variables globales¶
Unités d’Ether¶
Un nombre littéral peut prendre un suffixe de « wei », « finney », « szabo » ou « ether » pour spécifier une sous-dénomination d’éther, où les nombres d’éther sans postfix sont supposés être Wei.
assert(1 wei == 1);
assert(1 szabo == 1e12);
assert(1 finney == 1e15);
assert(1 ether == 1e18);
Le seul effet du suffixe de sous-dénomination est une multiplication par une puissance de dix..
Unités de temps¶
Des suffixes comme seconds
, minutes
, hours
, days
et weeks
peuvent être utilisés après les nombres littéraux pour spécifier les unités de temps où les secondes sont l’unité de base et les unités sont considérées naïvement de la façon suivante :
1 == 1 seconds
1 minutes == 60 seconds
1 hours == 60 minutes
1 days == 24 hours
1 weeks == 7 days
Faites attention si vous effectuez des calculs calendaires en utilisant ces unités, parce que chaque année n’est pas égale à 365 jours ni même chaque jour n’a 24 heures à cause des secondes bissextiles. Les secondes intercalaires étant imprévisibles, une bibliothèque de calendrier exacte doit être mise à jour par un oracle externe.
Note
Le suffixe years
a été supprimé dans la version 0.5.0 pour les raisons ci-dessus.
Ces suffixes ne peuvent pas être appliqués aux variables. Si vous voulez interpréter une variable d’entrée en jours, par exemple, vous pouvez le faire de la manière suivante:
function f(uint start, uint daysAfter) public {
if (now >= start + daysAfter * 1 days) {
// ...
}
}
Variables spéciales et fonctions¶
Il y a des variables et des fonctions spéciales qui existent toujours dans l’espace de nommage global et qui sont principalement utilisées pour fournir des informations sur la chaîne de blocs ou sont des fonctions utilitaires générales.
Propriétés du bloc et des transactions¶
blockhash(uint blockNumber) returns (bytes32)
: hash du numéro de bloc passé - mnarche seulement pour les 256 plus récents, excluant le bloc courantblock.coinbase
(address payable
): addresse du mineur du bloc courantblock.difficulty
(uint
): difficulté du bloc courantblock.gaslimit
(uint
): limite de gas actuelleblock.number
(uint
): numéro du bloc courantblock.timestamp
(uint
): timestamp du bloc en temps unix (secondes)gasleft() returns (uint256)
: gas restantmsg.data
(bytes calldata
): calldata completmsg.sender
(address payable
): expéditeur du message (appel courant)msg.sig
(bytes4
): 4 premiers octets calldata (i.e. identifiant de function)msg.value
(uint
): nombre de wei envoyés avec le messagenow
(uint
): alias pourblock.timestamp
tx.gasprice
(uint
): prix de la transaction en gastx.origin
(address payable
): expéditeur de la transaction (appel global complet)
Note
Les valeurs de tous les membres de msg
, y compris msg.sender``et ``msg.value
peuvent changer pour chaque appel de fonction external.
Ceci inclut les appels aux fonctions de librairies.
Note
Ne vous basez pas sur block.timestamp
, now
ou blockhash
comme source de hasard, à moins de savoir ce que vous faites.
L’horodatage et le hashage du bloc peuvent tous deux être influencés dans une certaine mesure par les mineurs. Les mauvais acteurs de la communauté minière peuvent par exemple exécuter une fonction de casino sur un hash choisi et simplement réessayer un hash différent s’ils n’ont pas reçu d’argent.
L’horodatage du bloc courant doit être strictement supérieur à celui du dernier bloc, mais la seule garantie est qu’il se situera entre les horodatages de deux blocs consécutifs dans la chaîne canonique.
Note
Les hashs de blocs ne sont pas disponibles pour tous les blocs pour des raisons d’évolutivité/place. Vous ne pouvez accéder qu’aux hachages des 256 blocs les plus récents, toutes les autres valeurs seront nulles.
Note
La fonction blockhash
était auparavant connue sous le nom block.blockhash
. Elle a été dépréciée dans la version 0.4.22 et supprimée dans la version 0.5.0.
Note
La fonction gasleft
était auparavant connue sous le nom de msg.gas
. Elle a été dépréciée dans la version 0.4.21 et supprimée dans la version 0.5.0.
Fonctions d’encodage et de décodage de l’ABI¶
abi.decode(bytes memory encodedData, (...)) returns (...)
: l’ABI décode les données données, tandis que les types sont donnés entre parenthèses comme second argument. Exemple :(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))
abi.encode(...) returns (bytes memory)
: l’ABI encode les arguments passés.abi.encodePacked(...) returns (bytes memory)
: exécute l”encodage structuré des arguments donnésabi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)
: l’ABI-encode les arguments donnés à partir du second et précède le sélecteur des quatre octets donnés.abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)
: équivalent àabi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)`
Note
Ces fonctions d’encodage peuvent être utilisées pour créer des données pour des appels de fonctions externes sans réellement appeler une fonction externe. De plus, keccak256(abi.encododePacked(a, b))
est un moyen de calculer le hash des données structurées (bien qu’il soit possible de créer une collision de hachage
en utilisant différents types d’entrées).
Voir la documentation sur le mode d’encodage <abi_packed_mode> pour plus de détails sur l’encodage.
Gestion des erreurs¶
Voir la section dédiée sur assert and require pour plus de détails sur la gestion des erreurs et quand utiliser quelle fonction.
assert(bool condition)
:- entraîne l’utilisation d’un opcode invalide et donc la réversion du changement d’état si la condition n’est pas remplie - à utiliser pour les erreurs internes.
require(bool condition)
:revert
si la condition n’est pas remplie - à utiliser en cas d’erreurs dans les entrées ou les composants externes.require(bool condition, string memory message)
:revert
si la condition n’est pas remplie - à utiliser en cas d’erreurs dans les entrées ou les composants externes. Fournit également un message d’erreur.revert()
:- annuler l’exécution et annuler les changements d’état
revert(string memory reason)
:- annuler l’exécution et annuler les changements d’état, fournissant une phrase explicative
Fonctions mathématiques et cryptographiques¶
addmod(uint x, uint y, uint k) returns (uint)
:- calcule
(x + y) % k
où l’addition est effectuée avec une précision arbitraire et n’overflow pas à2**256
.assert
quek != 0
à partir de la version 0.5.0. mulmod(uint x, uint y, uint k) returns (uint)
:- calcule
(x * y) % k
où la multiplication est effectuée avec une précision arbitraire et n’overflow pas à2**256
.assert
quek != 0
à partir de la version 0.5.0. keccak256(bytes memory) returns (bytes32)
:- calcule le hash Keccak-256 du paramètre
sha256(bytes memory) returns (bytes32)
:- calcule le hash SHA-256 du paramètre
ripemd160(bytes memory) returns (bytes20)
:- calcule le hash RIPEMD-160 du paramètre
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
:- récupérer l’adresse associée à la clé publique à partir de la signature de la courbe elliptique ou retourner zéro sur erreur. (exemple)
Note
La fonction ecrecover
renvoie une address
, et non une address payable
. Voir adresse payable pour la conversion, au cas où vous auriez besoin de transférer des fonds à l’adresse récupérée.
Il se peut que vous rencontriez out-of-gas
pour sha256
, ripemd160
ou erecover
sur une blockchain privée. La raison en est que ces contrats sont mis en œuvre sous la forme de contrats dits précompilés et que ces contrats n’existent réellement qu’après avoir reçu le premier message (bien que leur code contrat soit codé en dur). Les messages à des contrats inexistants sont plus coûteux et l’exécution se heurte donc à une erreur out-of-gas. Une solution de contournement pour ce problème est d’envoyer d’abord, par exemple, 1 Wei à chacun des contrats avant de les utiliser dans vos contrats réels. Le problème n’existe pas sur la cha^ine publique Ethereum ni sur les différents testnets officiels.
Note
Il y avait un alias pour keccak256
appelé sha3
, qui a été supprimé dans la version 0.5.0. pour éviter la confusion
Membres du type address¶
<address>.balance
(uint256
):- balance de l”Adresses en Wei
<address payable>.transfer(uint256 amount)
:- envoie la quantité donnée de Wei à adresse,
revert
en cas d’échec, envoie 2300 gas (non réglable) <address payable>.send(uint256 amount) returns (bool)
:- envoie la quantité donnée de Wei à adresse, retourne
false
en cas d’échec, envoie 2300 gas (non réglable) <address>.call(bytes memory) returns (bool, bytes memory)
:- émett un appel de bas niveau
CALL
avec la charge utile donnée, renvoie l’état de réussite et les données de retour, achemine tout le gas disponible ou un montant spécifié <address>.delegatecall(bytes memory) returns (bool, bytes memory)
:- émet un appel de bas niveau
DELEGATECALL
avec la charge utile donnée, retourne les données de succès et de retour, achemine tout le gas disponible ou un montant spécifié <address>.staticcall(bytes memory) returns (bool, bytes memory)
:- émettre un appel de bas niveau
STATICCALL
avec la charge utile donnée, retourne les conditions de succès et les données de retour, achemine tout le gas disponible ou un montant spécifié
Pour plus d’informations, voir la section sur adresse.
Avertissement
Il y a certains dangers à utiliser l’option send
: Le transfert échoue si la profondeur de la pile d’appels est à 1024 (cela peut toujours être forcé par l’appelant) et il échoue également si le destinataire manque de gas. Donc, afin d’effectuer des transferts d’éther en toute sécurité, vérifiez toujours la valeur de retour de send
, utilisez transfer
ou mieux encore :
Utilisez un modèle où le bénéficiaire retire l’argent.
Note
Avant la version 0.5.0, Solidity permettait aux membres d’adresses d’être accessibles par une instance de contrat, par exemple this.balance
.
Ceci est maintenant interdit et une conversion explicite en adresse doit être faite : address(this).balance
.
Note
Si l’accès aux variables d’état s’effectue via un appel de délégation de bas niveau, le plan de stockage des deux contrats doit être alignée pour que le contrat appelé puisse accéder correctement aux variables de stockage du contrat appelant par leur nom. Ce n’est bien sûr pas le cas si les pointeurs de stockage sont passés comme arguments de fonction comme dans le cas des fonctions de librairies (bibliothèques) de haut niveau.
Note
Avant la version 0.5.0, .call
, .delegatecall
et staticcall
ne renvoyaient que la condition de succès et non les données de retour.
Note
Avant la version 0.5.0, il y avait un membre appelé callcode
avec une sémantique similaire mais légèrement différente de celle de delegatecall
.
Variables relatives au contrat¶
this
(type du contrat courant):- le contrat en cours, explicitement convertible en Adresses.
selfdestruct(address payable destinataire_des_fonds)
:- détruire le contrat en cours, en envoyant ses fonds à l’adresse Adresses indiquée
En outre, toutes les fonctions du contrat en cours peuvent être appelées directement, y compris la fonction en cours.
Note
Avant la version 0.5.0, il existait une fonction appelée suicide
avec la même sémantique que selfdestruct
.