Cheat Sheet Solidity
Structure d'un contrat
Chaque fichier commence par une licence et un pragma ; le contrat est l'unité de déploiement.
| Syntaxe | Signification |
|---|---|
// SPDX-License-Identifier: MIT | Commentaire de licence attendu par le compilateur en ligne 1 |
pragma solidity ^0.8.0; | Version du compilateur pour laquelle le fichier est écrit |
contract Counter { ... } | Déclarer un contrat (état + fonctions) |
constructor(uint start) { count = start; } | S'exécute une seule fois, au déploiement |
import "./Token.sol"; | Importer un autre fichier |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | Importer un package de bibliothèque |
interface IToken { function balanceOf(address a) external view returns (uint); } | Déclarer une interface (sans corps) |
library Math { function min(uint a, uint b) internal pure returns (uint) { ... } } | Une bibliothèque de fonctions réutilisables |
Types valeur
Les entiers ont une taille fixe et pas de décimales ; 0.8 revert en cas de dépassement.
| Type | Ce qu'il contient |
|---|---|
uint256 / uint | Entier non signé, de 0 à 2^256 - 1 (uint est uint256) |
uint8, uint16, ... uint128 | Entiers non signés plus petits, par pas de 8 bits |
int256 / int | Entier signé (négatifs autorisés) |
bool | true ou false |
address | Adresse de compte ou de contrat sur 20 octets |
address payable | Adresse pouvant recevoir de l'Ether via transfer/send |
bytes32, bytes1... | Tableaux d'octets de taille fixe |
enum Status { Open, Closed } | Ensemble nommé de constantes, stocké en uint8 |
1 ether, 1 gwei, 1 wei | Unités d'Ether : 1 ether = 10^18 wei |
1 days, 2 hours, 30 minutes | Unités de temps, en secondes |
Types référence et emplacement des données
Tableaux, strings, bytes, structs et mappings vivent en storage, memory ou calldata.
| Syntaxe | Signification |
|---|---|
string memory name | Chaîne UTF-8 dynamique (copie temporaire) |
bytes memory data | Tableau d'octets dynamique |
uint[] public scores; | Tableau dynamique en storage |
uint[3] fixed; | Tableau de taille fixe de 3 éléments |
uint[] memory tmp = new uint[](5); | Allouer un tableau en memory |
scores.push(42); | Ajouter à la fin d'un tableau en storage |
scores.pop(); | Retirer le dernier élément |
scores.length | Nombre d'éléments |
storage | Persistant, on-chain, coûteux en écriture |
memory | Temporaire, vit le temps d'un appel |
calldata | Entrée de fonction externe en lecture seule, la moins chère |
Mappings et structs
Un mapping est une table de hachage sans longueur ni itération ; une struct regroupe des champs.
| Syntaxe | Signification |
|---|---|
mapping(address => uint) public balances; | Stockage clé-valeur, chaque clé existe (0 par défaut) |
balances[msg.sender] += 1; | Lire/écrire par clé |
mapping(address => mapping(address => uint)) allowance; | Mapping imbriqué |
struct User { string name; uint age; bool active; } | Définir une struct |
User memory u = User("Ada", 36, true); | Créer une struct en memory |
User memory u = User({name: "Ada", age: 36, active: true}); | Création avec champs nommés |
users[msg.sender] = u; | Stocker une struct dans un mapping |
users[msg.sender].age = 37; | Mettre à jour un champ en storage |
delete users[msg.sender]; | Réinitialiser aux valeurs par défaut |
Fonctions et visibilité
Chaque fonction indique qui peut l'appeler et si elle lit ou écrit l'état.
| Syntaxe | Signification |
|---|---|
function add(uint a, uint b) public pure returns (uint) { return a + b; } | Une fonction avec paramètres et valeur de retour |
public | Appelable de partout (intérieur et extérieur) |
external | Appelable uniquement depuis l'extérieur du contrat |
internal | Ce contrat et ceux qui en héritent |
private | Ce contrat uniquement |
view | Lit l'état, ne l'écrit jamais |
pure | Ne lit aucun état |
payable | Peut recevoir de l'Ether avec l'appel |
returns (uint sum, bool ok) | Plusieurs valeurs de retour nommées |
(uint s, bool ok) = f(); | Déstructurer plusieurs retours |
uint public count; | Une variable d'état publique obtient un getter automatique count() |
Modifiers, constantes et héritage
Réutilisez les vérifications avec des modifiers ; figez les valeurs avec constant et immutable.
| Syntaxe | Signification |
|---|---|
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } | Définir un modifier (_ = exécuter le corps de la fonction) |
function withdraw() public onlyOwner { ... } | Appliquer un modifier |
uint public constant MAX = 100; | Constante de compilation |
address public immutable owner; | Fixée une fois dans le constructeur, puis figée |
contract Token is ERC20, Ownable { ... } | Hériter d'autres contrats |
function f() public virtual { ... } | Autoriser la redéfinition |
function f() public override { ... } | Redéfinir une fonction parente |
super.f(); | Appeler l'implémentation du parent |
abstract contract Base { function f() public virtual; } | Contrat avec des fonctions non implémentées |
Flux de contrôle
Les instructions habituelles de la famille C ; pas de switch, et les boucles coûtent du gas à chaque itération.
| Syntaxe | Signification |
|---|---|
if (x > 5) { ... } else if (x > 2) { ... } else { ... } | Branches conditionnelles |
for (uint i = 0; i < n; i++) { ... } | Boucle à compteur |
while (x < 10) { x++; } | Boucler tant qu'une condition est vraie |
do { ... } while (cond); | S'exécute au moins une fois |
break; / continue; | Sortir de la boucle / passer à l'itération suivante |
x > 0 ? a : b | Expression ternaire |
a / b | Division entière (perd le reste) |
a % b | Reste |
a ** 2 | Exponentiation |
unchecked { x++; } | Ignorer les vérifications de dépassement (économise du gas, à utiliser avec prudence) |
Erreurs : require, revert, assert
Une vérification qui échoue annule toute la transaction et rembourse le gas non utilisé.
| Syntaxe | Signification |
|---|---|
require(amount > 0, "Amount must be positive"); | Valider une entrée ou l'état ; revert avec un message |
revert("Not allowed"); | Interrompre sans condition |
error Insufficient(uint available, uint requested); | Déclarer une erreur personnalisée (moins chère que les strings) |
revert Insufficient(balance, amount); | Revert avec une erreur personnalisée |
assert(total == a + b); | Vérifier un invariant qui ne doit jamais échouer |
try token.transfer(to, amt) returns (bool ok) { ... } catch { ... } | Gérer un appel externe qui échoue |
Événements
Les événements écrivent des logs auxquels les applications off-chain peuvent s'abonner ; ils ne sont pas lisibles depuis les contrats.
| Syntaxe | Signification |
|---|---|
event Transfer(address indexed from, address indexed to, uint value); | Déclarer un événement |
emit Transfer(msg.sender, to, amount); | L'émettre |
indexed | Paramètre filtrable (jusqu'à 3 par événement) |
event Log(string message); | Tout type ABI peut être loggé |
Ether, adresses et variables globales
Le contexte de la transaction vient de msg, block et tx.
| Syntaxe | Signification |
|---|---|
msg.sender | Adresse qui a appelé cette fonction |
msg.value | Wei envoyés avec l'appel (nécessite payable) |
block.timestamp | Horodatage du bloc courant (secondes depuis l'epoch) |
block.number | Hauteur du bloc courant |
tx.origin | Le compte externe (EOA) à l'origine de la tx (à éviter pour l'authentification) |
address(this).balance | Solde en Ether de ce contrat |
payable(to).transfer(1 ether); | Envoyer de l'Ether, revert en cas d'échec |
(bool ok, ) = to.call{value: amt}(""); | Envoi bas niveau, renvoie un indicateur de succès |
receive() external payable {} | S'exécute lors d'un simple transfert d'Ether |
fallback() external payable {} | S'exécute quand aucune fonction ne correspond |
keccak256(abi.encodePacked(a, b)) | Hacher des valeurs |
abi.encode(x), abi.decode(data, (uint)) | Encoder / décoder des données ABI |
Toute la syntaxe Solidity dont vous avez besoin, sur une seule page. Cette cheat sheet Solidity est une référence rapide pour le langage des smart contracts d'Ethereum et de toutes les chaînes EVM : déclarer un contrat, choisir ses types, stocker des données dans des mappings et des structs, écrire des fonctions avec la bonne visibilité et la bonne mutabilité, et les protéger avec require, des modifiers et des événements.
La syntaxe présentée ici est celle de Solidity 0.8, qui vérifie les dépassements arithmétiques par défaut et fonctionne avec Remix, Hardhat et Foundry. Copiez ce qu'il vous faut, ou essayez-le en direct dans le playground Solidity : écrivez un contrat, compilez-le et exécutez-le sur une EVM dans votre navigateur.