Utilisation du compilateur
Utilisation du compilateur en ligne de commande
Note
Cette section ne s’applique pas à solcjs, même s’il est utilisé en mode ligne de commande.
Utilisation de base
L’une des cibles de construction du référentiel Solidity est solc
, le compilateur en ligne de commande de Solidity.
L’utilisation de solc --help
vous fournit une explication de toutes les options. Le compilateur peut produire diverses sorties, allant de simples binaires et assemblages sur un arbre syntaxique abstrait (parse tree) à des estimations de l’utilisation du gaz.
Si vous voulez seulement compiler un seul fichier, vous le lancez comme solc --bin sourceFile.sol
et il imprimera le binaire. Si vous voulez obtenir certaines des variantes de sortie plus avancées de solc
, il est probablement préférable de lui dire de tout sortir dans des fichiers séparés en utilisant solc -o outputDirectory --bin --ast-compact-json --asm sourceFile.sol
.
Options de l’optimiseur
Avant de déployer votre contrat, activez l’optimiseur lors de la compilation en utilisant solc --optimize --bin sourceFile.sol
.
Par défaut, l’optimiseur optimisera le contrat en supposant qu’il est appelé 200 fois au cours de sa durée de vie
(plus précisément, il suppose que chaque opcode est exécuté environ 200 fois).
Si vous voulez que le déploiement initial du contrat soit moins cher et que les exécutions de fonctions ultérieures soient plus coûteuses,
définissez-le à --optimize-runs=1
. Si vous vous attendez à de nombreuses transactions et que vous ne vous souciez pas des coûts de
la taille de la sortie, définissez --optimize-runs
à un nombre élevé.
Ce paramètre a des effets sur les éléments suivants (cela pourrait changer dans le futur) :
la taille de la recherche binaire dans la routine d’envoi des fonctions
la façon dont les constantes comme les grands nombres ou les chaînes de caractères sont stockées.
Chemin de base et remappage des importations
Le compilateur en ligne de commande lira automatiquement les fichiers importés depuis le système de fichiers, mais
il est également possible de fournir des redirections path en utilisant prefix=path
de la manière suivante :
solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol
Ceci indique essentiellement au compilateur de rechercher tout ce qui commence par
github.com/ethereum/dapp-bin/
sous /usr/local/lib/dapp-bin
.
Lorsque vous accédez au système de fichiers pour rechercher des importations, les chemins qui ne commencent pas par ./ ou ../
sont traités comme relatifs aux répertoires spécifiés en utilisant les options --base-path
et -include-path
(ou le répertoire de travail actuel si le chemin de base n’est pas spécifié).
De plus, la partie du chemin ajoutée via ces options n’apparaîtra pas dans les métadonnées du contrat.
Pour des raisons de sécurité, le compilateur a des restrictions sur les répertoires auxquels il peut accéder.
Les répertoires des fichiers sources spécifiés sur la ligne de commande et les chemins cibles des
remappings sont automatiquement autorisés à être accédés par le lecteur de fichiers, mais
tout le reste est rejeté par défaut.
Des chemins supplémentaires (et leurs sous-répertoires) peuvent être autorisés via la commande
--allow-paths /sample/path,/another/sample/path
.
Tout ce qui se trouve à l’intérieur du chemin spécifié par --base-path
est toujours autorisé.
Ce qui précède n’est qu’une simplification de la façon dont le compilateur gère les chemins d’importation. Pour une explication détaillée avec des exemples et une discussion des cas de coin, veuillez vous référer à la section sur résolution de chemin.
Liens entre les bibliothèques
Si vos contrats utilisent libraries, vous remarquerez que le bytecode contient des sous-chaînes de la forme __$53aea86b7d70b31448b230b20ae141a537$__
. Il s’agit de caractères de remplacement pour les adresses réelles des bibliothèques.
Le placeholder est un préfixe de 34 caractères de l’encodage hexadécimal du hachage keccak256 du nom de bibliothèque entièrement qualifié.
Le fichier de bytecode contiendra également des lignes de la forme // <placeholder> -> <fq library name>
à la fin pour aider à
identifier les bibliothèques que les placeholders représentent. Notez que le nom de bibliothèque pleinement qualifié
est le chemin de son fichier source et le nom de la bibliothèque séparés par :
.
Vous pouvez utiliser solc
comme linker, ce qui signifie qu’il insérera les adresses des bibliothèques pour vous à ces endroits :
Soit vous ajoutez --libraries "file.sol:Math=0x1234567890123456789012345678901234567890 file.sol:Heap=0xabCD5678901234567890123458901234567890"
à votre commande pour fournir une adresse pour chaque bibliothèque (utilisez des virgules ou des espaces comme séparateurs) ou stockez la chaîne dans un fichier (une bibliothèque par ligne) et lancez solc
en utilisant –libraries fileName`.
Note
À partir de la version 0.8.1 de Solidity, on accepte =
comme séparateur entre bibliothèque et adresse, et :
comme séparateur est déprécié. Il sera supprimé à l’avenir. Actuellement, --libraries "file.sol:Math:0x123456789012345678901234567890123458901234567890 file.sol:Heap:0xabCD567890123456789012345890123234567890"
fonctionnera également.
Si solc
est appelé avec l’option --standard-json
, il attendra une entrée JSON (comme expliqué ci-dessous) sur l’entrée standard, et retournera une sortie JSON sur la sortie standard. C’est l’interface recommandée pour des utilisations plus complexes et particulièrement automatisées. Le processus se terminera toujours dans un état « success » et rapportera toute erreur via la sortie JSON.
L’option --base-path
est également traitée en mode standard-json.
Si solc
est appelé avec l’option --link
, tous les fichiers d’entrée sont interprétés comme des binaires non liés (encodés en hexadécimal) dans le format __$53aea86b7d70b31448b230b20ae141a537$__
donné ci-dessus et sont liés in-place (si l’entrée est lue depuis stdin, elle est écrite sur stdout). Toutes les options sauf --libraries
sont ignorées (y compris -o
) dans ce cas.
Avertissement
La liaison manuelle des bibliothèques sur le bytecode généré est déconseillée car elle ne permet pas de mettre à jour les métadonnées du contrat. Puisque les métadonnées contiennent une liste de bibliothèques spécifiées au moment de la compilation et le bytecode contient un hash de métadonnées, vous obtiendrez des binaires différents, selon du moment où la liaison est effectuée.
Vous devez demander au compilateur de lier les bibliothèques au moment où un contrat est compilé, soit en
en utilisant l’option --libraries
de solc
ou la clé libraries
si vous utilisez l’interface
standard-JSON au compilateur.
Note
L’espace réservé à la bibliothèque était auparavant le nom pleinement qualifié de la bibliothèque elle-même
au lieu du hash de celui-ci. Ce format est toujours pris en charge par solc --link
mais
mais le compilateur ne l’affichera plus. Ce changement a été fait pour réduire
la probabilité de collision entre les bibliothèques, puisque seuls les 36 premiers caractères du nom de
du nom complet de la bibliothèque pouvaient être utilisés.
Réglage de la version de l’EVM sur la cible
Lorsque vous compilez le code de votre contrat, vous pouvez spécifier la version de la machine virtuelle d’Ethereum pour laquelle compiler afin d’éviter des caractéristiques ou des comportements particuliers.
Avertissement
La compilation pour la mauvaise version EVM peut entraîner un comportement erroné, étrange et défaillant. Veuillez vous assurer, en particulier si vous exécutez une chaîne privée, que vous utilisez les versions EVM correspondantes.
Sur la ligne de commande, vous pouvez sélectionner la version EVM comme suit :
solc --evm-version <VERSION> contract.sol
Dans l’interface standard JSON, utilisez la clé "evmVersion"
dans le champ "settings"
:
{
"sources": {/* ... */},
"settings": {
"optimizer": {/* ... */},
"evmVersion": "<VERSION>"
}
}
Options de la cible
Vous trouverez ci-dessous une liste des versions EVM cibles et des modifications relatives au compilateur introduites à chaque version. La rétrocompatibilité n’est pas garantie entre chaque version.
homestead
(version la plus ancienne)
tangerineWhistle
Le coût du gaz pour l’accès à d’autres comptes a augmenté, ce qui est pertinent pour l’estimation du gaz et l’optimiseur.
Tout le gaz est envoyé par défaut pour les appels externes, auparavant une certaine quantité devait être conservée.
spuriousDragon
Le coût du gaz pour l’opcode
exp
a augmenté, ce qui est important pour l’estimation du gaz et l’optimiseur.
byzantium
Les opcodes
returndatacopy
,returndatasize
etstaticcall
sont disponibles en assembly.L’opcode
staticcall
est utilisé lors de l’appel de fonctions de vue ou de fonctions pures non libérées, ce qui empêche les fonctions de modifier l’état au niveau de l’EVM, c’est-à-dire qu’il s’applique même lorsque vous utilisez des conversions de type invalides.Il est possible d’accéder aux données dynamiques renvoyées par les appels de fonctions.
Introduction de l’opcode
revert
, ce qui signifie querevert()
ne gaspillera pas de gaz.
constantinople
Les opcodes
create2
,extcodehash'', ``shl
,shr
etsar
sont disponibles en assembleur.Les opérateurs de décalage utilisent des opcodes de décalage et nécessitent donc moins de gaz.
petersburg
Le compilateur se comporte de la même manière qu’avec constantinople.
istanbul
Les opcodes
chainid
et ``selfbalance`” sont disponibles en assemblage.
berlin
Les coûts du gaz pour
LOAD
,*CALL
,BALANCE
,EXT
etSELFDESTRUCT
ont augmenté. Le compilateur suppose des coûts de gaz froid pour de telles opérations. Ceci est pertinent pour l’estimation des gaz et l’optimiseur.
Description JSON des entrées et sorties du compilateur
La manière recommandée de s’interfacer avec le compilateur Solidity, surtout pour les configurations plus complexes et automatisées est l’interface dite d’entrée-sortie JSON. La même interface est fournie par toutes les distributions du compilateur.
Les champs sont généralement susceptibles d’être modifiés, certains sont optionnels (comme indiqué), mais nous essayons de ne faire que des changements compatibles avec le passé.
L’API du compilateur attend une entrée au format JSON et produit le résultat de la compilation dans une sortie au format JSON. La sortie d’erreur standard n’est pas utilisée et le processus se terminera toujours dans un état de « succès », même s’il y a eu des erreurs. Les erreurs sont toujours signalées dans le cadre de la sortie JSON.
Les sous-sections suivantes décrivent le format à travers un exemple. Les commentaires ne sont bien sûr pas autorisés et sont utilisés ici uniquement à des fins explicatives.
Description de l’entrée
{
// Requis : Langue du code source. Les langages actuellement pris en charge sont "Solidity" et "Yul".
"language": "Solidity",
// Requis
"sources":
{
// Les clés ici sont les noms "globaux" des fichiers sources,
// les importations peuvent utiliser d'autres fichiers via les remappings (voir ci-dessous).
"myFile.sol":
{
// Facultatif : hachage keccak256 du fichier source.
// Il est utilisé pour vérifier le contenu récupéré s'il est importé via des URL.
"keccak256": "0x123...",
// Obligatoire (sauf si "content" est utilisé, voir ci-dessous) : URL(s) vers le fichier source.
// Les URL doivent être importées dans cet ordre et le résultat doit être vérifié par rapport à l'empreinte
// le hachage keccak256 (si disponible). Si le hachage ne correspond pas ou si aucune des
// URL n'aboutit à un succès, une erreur doit être signalée.
// En utilisant l'interface en ligne de commande, seuls les chemins de systèmes de fichiers sont pris en charge.
// Avec l'interface JavaScript, l'URL sera transmise au callback de lecture fourni par l'utilisateur.
// Ainsi, toute URL prise en charge par le callback peut être utilisée.
"urls":
[
"bzzr://56ab...",
"ipfs://Qma...",
"/tmp/path/to/file.sol"
// Si des fichiers sont utilisés, leurs répertoires doivent être ajoutés à la ligne de commande via
// `--allow-paths <path>`.
]
},
"destructible":
{
// Facultatif : keccak256 hash du fichier source
"keccak256": "0x234...",
// Obligatoire (sauf si "urls" est utilisé) : contenu littéral du fichier source
"content": "contract destructible is owned { function shutdown() { if (msg.sender == owner) selfdestruct(owner); } }"
}
},
// Optionnel
"settings":
{
// Facultatif : Arrête la compilation après l'étape donnée. Actuellement, seul "parsing" est valide ici
"stopAfter": "parsing",
// Facultatif : Liste triée de réaffectations
"remappings": [ ":g=/dir" ],
// Facultatif : Paramètres de l'optimiseur
"optimizer": {
// Désactivé par défaut.
// NOTE : enabled=false laisse toujours certaines optimisations activées. Voir les commentaires ci-dessous.
// ATTENTION : Avant la version 0.8.6, l'omission de la clé 'enabled' n'était pas équivalente à la mise en place de la clé 'enabled'.
// l'activer à false et désactiverait en fait toutes les optimisations.
"enabled": true,
// Optimisez en fonction du nombre de fois que vous avez l'intention d'exécuter le code.
// Les valeurs les plus basses optimisent davantage le coût de déploiement initial, les valeurs les plus élevées optimisent davantage les utilisations à haute fréquence.
// Plus les valeurs sont faibles, plus l'optimisation est axée sur le coût du déploiement initial.
// Plus les valeurs sont élevées, plus l'optimisation est axée sur un usage fréquent.
"runs": 200,
// Activez ou désactivez les composants de l'optimiseur en détail.
// L'interrupteur "enabled" ci-dessus fournit deux valeurs par défaut qui peuvent être
// modifiables ici. Si "details" est donné, "enabled" peut être omis.
"details": {
// L'optimiseur de trou d'homme est toujours activé si aucun détail n'est donné,
// utilisez les détails pour le désactiver.
"peephole": true,
// L'inliner est toujours activé si aucun détail n'est donné,
// utilisez les détails pour le désactiver.
"inliner": true,
// L'enlèvement du jumpdest inutilisé est toujours activé si aucun détail n'est donné,
// utilisez les détails pour le désactiver.
"jumpdestRemover": true,
// Réorganise parfois les littéraux dans les opérations commutatives.
"orderLiterals": false,
// Supprime les blocs de code dupliqués
"deduplicate": false,
// L'élimination des sous-expressions communes, c'est l'étape la plus compliquée mais
// peut également fournir le gain le plus important.
"cse": false,
// Optimiser la représentation des nombres littéraux et des chaînes de caractères dans le code.
"constantOptimizer": false,
// Le nouvel optimiseur Yul. Opère principalement sur le code du codeur ABI v2
// et de l'assemblage en ligne.
// Il est activé en même temps que le réglage de l'optimiseur global
// et peut être désactivé ici.
// Avant Solidity 0.6.0, il devait être activé par ce commutateur.
"yul": false,
// Tuning options for the Yul optimizer.
"yulDetails": {
// Améliore l'allocation des emplacements de pile pour les variables, peut libérer les emplacements de pile plus tôt.
// Activé par défaut si l'optimiseur Yul est activé.
"stackAllocation": true,
// Sélectionnez les étapes d'optimisation à appliquer.
// Facultatif, l'optimiseur utilisera la séquence par défaut si elle est omise.
"optimizerSteps": "dhfoDgvulfnTUtnIf..."
}
}
},
// Version de l'EVM pour laquelle il faut compiler.
// Affecte la vérification de type et la génération de code. Peut être homestead,
// tangerineWhistle, spuriousDragon, byzantium, constantinople, petersburg, istanbul ou berlin.
"evmVersion": "byzantium",
// Facultatif : Modifier le pipeline de compilation pour passer par la représentation intermédiaire de Yul.
// Il s'agit d'une fonctionnalité hautement EXPERIMENTALE, à ne pas utiliser en production. Elle est désactivée par défaut.
"viaIR": true,
// Facultatif : Paramètres de débogage
"debug": {
// Comment traiter les chaînes de motifs de retour (et d'exigence). Les paramètres sont
// "default", "strip", "debug" et "verboseDebug".
// "default" n'injecte pas les chaînes revert générées par le compilateur et conserve celles fournies par l'utilisateur.
// "strip" supprime toutes les chaînes revert (si possible, c'est-à-dire si des littéraux sont utilisés) en conservant les effets secondaires.
// "debug" injecte des chaînes pour les revert internes générés par le compilateur, implémenté pour les encodeurs ABI V1 et V2 pour le moment.
// "verboseDebug" ajoute même des informations supplémentaires aux chaînes de revert fournies par l'utilisateur (pas encore implémenté).
"revertStrings": "default",
// Facultatif : quantité d'informations de débogage supplémentaires à inclure dans les commentaires de l'EVM
// produit et dans le code Yul. Les composants disponibles sont :
// - `location` : Annotations de la forme `@src <index>:<start>:<end>` indiquant
// l'emplacement de l'élément correspondant dans le fichier Solidity original, où :
// - `<index>` est l'index du fichier correspondant à l'annotation `@use-src`,
// - `<start>` est l'indice du premier octet à cet emplacement,
// - `<end>` est l'indice du premier octet après cet emplacement.
// - `snippet` : Un extrait de code d'une seule ligne provenant de l'emplacement indiqué par `@src`.
// L'extrait est cité et suit l'annotation `@src` correspondante.
// - `*` : Valeur joker qui peut être utilisée pour tout demander.
"debugInfo": ["location", "snippet"]
},
// Paramètres des métadonnées (facultatif)
"metadata": {
// Utiliser uniquement le contenu littéral et non les URL (faux par défaut)
"useLiteralContent": true,
// Utilisez la méthode de hachage donnée pour le hachage des métadonnées qui est ajouté au bytecode.
// Le hachage des métadonnées peut être supprimé du bytecode via l'option "none".
// Les autres options sont "ipfs" et "bzzr1".
// Si l'option est omise, "ipfs" est utilisé par défaut.
"bytecodeHash": "ipfs"
},
// Adresses des bibliothèques. Si toutes les bibliothèques ne sont pas données ici,
// il peut en résulter des objets non liés dont les données de sortie sont différentes.
"libraries": {
// La clé de premier niveau est le nom du fichier source dans lequel la bibliothèque est utilisée.
// Si des remappages sont utilisés, ce fichier source doit correspondre au chemin global
// après que les remappages aient été appliqués.
// Si cette clé est une chaîne vide, cela fait référence à un niveau global.
"myFile.sol": {
"MyLib": "0x123123..."
}
},
// Ce qui suit peut être utilisé pour sélectionner les sorties souhaitées en se basant
// sur les noms de fichiers et de contrats.
// Si ce champ est omis, alors le compilateur charge et effectue une vérification de type,
// mais ne générera aucune sortie en dehors des erreurs.
// La clé de premier niveau est le nom du fichier et la clé de second niveau est le nom du contrat.
// Un nom de contrat vide est utilisé pour les sorties qui ne sont pas liées à un contrat
// mais à l'ensemble du fichier source, comme l'AST.
// Une étoile comme nom de contrat fait référence à tous les contrats du fichier.
// De même, une étoile comme nom de fichier correspond à tous les fichiers.
// Pour sélectionner toutes les sorties que le compilateur peut éventuellement générer, utilisez
// "outputSelection : { "*" : { "*" : [ "*" ], "" : [ "*" ] } }"
// mais notez que cela pourrait ralentir inutilement le processus de compilation.
//
// Les types de sortie disponibles sont les suivants :
//
// Niveau fichier (nécessite une chaîne vide comme nom de contrat) :
// ast - AST de tous les fichiers sources
//
// Niveau du contrat (nécessite le nom du contrat ou "*") :
// abi - ABI
// devdoc - Documentation du développeur (natspec)
// userdoc - Documentation utilisateur (natspec)
// metadata - Métadonnées
// ir - Représentation intermédiaire Yul du code avant optimisation
// irOptimized - Représentation intermédiaire après optimisation
// storageLayout - Emplacements, décalages et types des variables d'état du contrat.
// evm.assembly - Nouveau format d'assemblage
// evm.legacyAssembly - Ancien format d'assemblage en JSON
// evm.bytecode.functionDebugData - Informations de débogage au niveau des fonctions.
// evm.bytecode.object - Objet bytecode
// evm.bytecode.opcodes - Liste d'opcodes
// evm.bytecode.sourceMap - Cartographie de la source (utile pour le débogage)
// evm.bytecode.linkReferences - Références de liens (si objet non lié)
// evm.bytecode.generatedSources - Sources générées par le compilateur.
// evm.deployedBytecode* - Bytecode déployé (a toutes les options que evm.bytecode a)
// evm.deployedBytecode.immutableReferences - Correspondance entre les identifiants AST et les plages de bytecode qui font référence aux immutables.
// evm.methodIdentifiers - La liste des hachages de fonctions
// evm.gasEstimates - Estimations des gaz de fonction
// ewasm.wast - Ewasm au format S-expressions de WebAssembly
// ewasm.wasm - Ewasm au format binaire WebAssembly
//
// Notez que l'utilisation d'un `evm`, `evm.bytecode`, `ewasm`, etc. sélectionnera chaque
// partie cible de cette sortie. De plus, `*` peut être utilisé comme un joker pour tout demander.
//
"outputSelection": {
"*": {
"*": [
"metadata", "evm.bytecode" // Activez les sorties de métadonnées et de bytecode de chaque contrat.
, "evm.bytecode.sourceMap" // Activez la sortie de la carte des sources pour chaque contrat.
],
"": [
"ast" // Active la sortie AST de chaque fichier.
]
},
// Active la sortie de l'abi et des opcodes de MonContrat définis dans le fichier def.
"def": {
"MyContract": [ "abi", "evm.bytecode.opcodes" ]
}
},
// L'objet modelChecker est expérimental et sujet à des modifications.
"modelChecker":
{
// Choisir les contrats qui doivent être analysés comme ceux qui sont déployés.
"contracts":
{
"source1.sol": ["contract1"],
"source2.sol": ["contract2", "contract3"]
},
// Choisir si les opérations de division et de modulo doivent être remplacées par
// multiplication avec des variables de type slack. La valeur par défaut est `true`.
// L'utilisation de `false` ici est recommandée si vous utilisez le moteur CHC
// et que vous n'utilisez pas Spacer comme solveur de Horn (en utilisant Eldarica, par exemple).
// Voir la section Vérification formelle pour une explication plus détaillée de cette option.
"divModWithSlacks": true,
// Choisissez le moteur de vérification de modèle à utiliser : all (par défaut), bmc, chc, none.
"engine": "chc",
// Choisissez quels types d'invariants doivent être signalés à l'utilisateur : contrat, réentrance.
"invariants": ["contract", "reentrancy"],
// Choisissez si vous souhaitez afficher toutes les cibles non prouvées. La valeur par défaut est `false`.
"showUnproved": true,
// Choisissez les solveurs à utiliser, s'ils sont disponibles.
// Voir la section Vérification formelle pour la description des solveurs.
"solvers": ["cvc4", "smtlib2", "z3"],
// Choisissez les cibles à vérifier : constantCondition,
// underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds.
// Si l'option n'est pas donnée, toutes les cibles sont vérifiées par défaut,
// sauf underflow/overflow pour Solidity >=0.8.7.
// Voir la section Vérification formelle pour la description des cibles.
"targets": ["underflow", "overflow", "assert"],
// Délai d'attente pour chaque requête SMT en millisecondes.
// Si cette option n'est pas donnée, le SMTChecker utilisera une limite de ressources déterministe
// par défaut.
// Un délai d'attente de 0 signifie qu'il n'y a aucune restriction de ressources ou de temps pour les requêtes.
"timeout": 20000
}
}
}
Description de la sortie
{
// Facultatif : non présent si aucune erreur/avis/infos n'a été rencontrée.
"errors": [
{
// Facultatif : Emplacement dans le fichier source.
"sourceLocation": {
"file": "sourceFile.sol",
"start": 0,
"end": 100
},
// Facultatif : Autres lieux (par exemple, lieux de déclarations conflictuelles)
"secondarySourceLocations": [
{
"file": "sourceFile.sol",
"start": 64,
"end": 92,
"message": "L'autre déclaration est ici :"
}
],
// Obligatoire : Type d'erreur, tel que "TypeError", "InternalCompilerError", "Exception", etc.
// Voir ci-dessous pour la liste complète des types.
"type": "TypeError",
// Obligatoire : Composant d'où provient l'erreur, tel que "general", "ewasm", etc.
"component": "general",
// Obligatoire ("error", "warning" ou "info", mais veuillez noter que cela pourrait être étendu à l'avenir)
"severity": "error",
// Facultatif : code unique pour la cause de l'erreur.
"errorCode": "3141",
// Obligatoire
"message": "Mot clé invalide",
// Facultatif : le message formaté avec l'emplacement de la source
"formattedMessage": "sourceFile.sol:100: Invalid keyword"
}
],
// Il contient les sorties au niveau du fichier.
// Il peut être limité/filtré par les paramètres outputSelection.
"sources": {
"sourceFile.sol": {
// Identifiant de la source (utilisé dans les cartes de sources)
"id": 1,
// L'objet AST
"ast": {}
}
},
// Il contient les sorties au niveau du contrat.
// Il peut être limité/filtré par les paramètres outputSelection.
"contracts": {
"sourceFile.sol": {
// Si la langue utilisée ne comporte pas de noms de contrat, ce champ doit être égal à une chaîne vide.
"ContractName": {
// L'ABI du contrat Ethereum. S'il est vide, il est représenté comme un tableau vide.
// See https://docs.soliditylang.org/en/develop/abi-spec.html
"abi": [],
// Voir la documentation sur la sortie des métadonnées (chaîne JSON sérialisée).
"metadata": "{/* ... */}",
// Documentation utilisateur (natspec)
"userdoc": {},
// Documentation pour les développeurs (natspec)
"devdoc": {},
// Représentation intermédiaire (chaîne de caractères)
"ir": "",
// Voir la documentation sur l'agencement du stockage.
"storageLayout": {"storage": [/* ... */], "types": {/* ... */} },
// Sorties liées à l'EVM
"evm": {
// Assemblée (chaîne de caractères)
"assembly": "",
// Assemblage à l'ancienne (objet)
"legacyAssembly": {},
// Bytecode et détails connexes.
"bytecode": {
// Débogage des données au niveau des fonctions.
"functionDebugData": {
// Suit maintenant un ensemble de fonctions incluant des fonctions définies par l'utilisateur.
// L'ensemble ne doit pas nécessairement être complet.
"@mint_13": { // Nom interne de la fonction
"entryPoint": 128, // Décalage d'octet dans le bytecode où la fonction commence (facultatif)
"id": 13, // AST ID de la définition de la fonction ou null pour les fonctions internes au compilateur (facultatif)
"parameterSlots": 2, // Nombre d'emplacements de pile EVM pour les paramètres de fonction (facultatif)
"returnSlots": 1 // Nombre d'emplacements de pile EVM pour les valeurs de retour (facultatif)
}
},
// Le bytecode sous forme de chaîne hexagonale.
"object": "00fe",
// Liste des opcodes (chaîne de caractères)
"opcodes": "",
// Le mappage de la source sous forme de chaîne. Voir la définition du mappage de la source.
"sourceMap": "",
// Tableau des sources générées par le compilateur. Actuellement, il ne
// contient qu'un seul fichier Yul.
"generatedSources": [{
// Yul AST
"ast": {/* ... */},
// Fichier source sous sa forme texte (peut contenir des commentaires)
"contents":"{ function abi_decode(start, end) -> data { data := calldataload(start) } }",
// ID du fichier source, utilisé pour les références aux sources, même "namespace" que les fichiers sources de Solidity.
"id": 2,
"language": "Yul",
"name": "#utility.yul"
}],
// S'il est donné, il s'agit d'un objet non lié.
"linkReferences": {
"libraryFile.sol": {
// Décalage des octets dans le bytecode.
// La liaison remplace les 20 octets qui s'y trouvent.
"Library1": [
{ "start": 0, "length": 20 },
{ "start": 200, "length": 20 }
]
}
}
},
"deployedBytecode": {
/* ..., */ // La même disposition que ci-dessus.
"immutableReferences": {
// Il existe deux références à l'immuable avec l'ID AST 3, toutes deux d'une longueur de 32 octets. L'une se trouve
// à l'offset 42 du bytecode, l'autre à l'offset 80 du bytecode.
"3": [{ "start": 42, "length": 32 }, { "start": 80, "length": 32 }]
}
},
// La liste des hachages de fonctions
"methodIdentifiers": {
"delegate(address)": "5c19a95c"
},
// Estimation des gaz de fonction
"gasEstimates": {
"creation": {
"codeDepositCost": "420000",
"executionCost": "infinite",
"totalCost": "infinite"
},
"external": {
"delegate(address)": "25000"
},
"internal": {
"heavyLifting()": "infinite"
}
}
},
// Sorties liées à l'Ewasm
"ewasm": {
// Format des expressions S
"wast": "",
// Format binaire (chaîne hexagonale)
"wasm": ""
}
}
}
}
}
Types d’erreurs
JSONError
: L’entrée JSON n’est pas conforme au format requis, par exemple, l’entrée n’est pas un objet JSON, la langue n’est pas supportée, etc.IOError
: Erreurs de traitement des entrées/sorties et des importations, telles qu’une URL non résoluble ou une erreur de hachage dans les sources fournies.ParserError
: Le code source n’est pas conforme aux règles du langage.DocstringParsingError
: Les balises NatSpec du bloc de commentaires ne peuvent pas être analysées.SyntaxError
: Erreur de syntaxe, comme l’utilisation de « continue » en dehors d’une boucle « for ».DeclarationError
: Noms d’identifiants invalides, impossibles à résoudre ou contradictoires. Par exemple, « Identifiant non trouvé ».TypeError
: Erreur dans le système de types, comme des conversions de types invalides, des affectations invalides, etc.UnimplementedFeatureError
: La fonctionnalité n’est pas supportée par le compilateur, mais devrait l’être dans les futures versions.InternalCompilerError
: Bogue interne déclenché dans le compilateur - il doit être signalé comme un problème.Exception
: Echec inconnu lors de la compilation - ceci devrait être signalé comme un problème.CompilerError
: Utilisation non valide de la pile du compilateur - ceci devrait être signalé comme un problème.FatalError
: Une erreur fatale n’a pas été traitée correctement - ceci devrait être signalé comme un problème.Warning
: Un avertissement, qui n’a pas arrêté la compilation, mais qui devrait être traité si possible.Info
: Une information que le compilateur pense que l’utilisateur pourrait trouver utile, mais qui n’est pas dangereuse et ne doit pas nécessairement être traitée.
Outils de compilation
solidity-upgrade
solidity-upgrade
peut vous aider à mettre à jour semi-automatiquement vos contrats
en fonction des changements de langue. Bien qu’il n’implémente pas et ne puisse pas implémenter tous
changements requis pour chaque version de rupture, il prend en charge ceux
qui, autrement, nécessiteraient de nombreux ajustements manuels répétitifs.
Note
solidity-upgrade
effectue une grande partie du travail, mais vos
contrats nécessiteront très probablement d’autres ajustements manuels. Nous vous recommandons
d’utiliser un système de contrôle de version pour vos fichiers. Cela permet de réviser et
éventuellement de revenir en arrière sur les modifications apportées.
Avertissement
solidity-upgrade
n’est pas considéré comme complet ou exempt de bogues, donc
veuillez l’utiliser avec précaution.
Modules de mise à niveau disponibles
Module |
Version |
Description |
---|---|---|
|
0.5.0 |
Les constructeurs doivent maintenant être définis à l’aide dumot-clé « constructeur ». |
|
0.5.0 |
La visibilité explicite des fonctions est
désormais obligatoire, La valeur par défaut est
|
|
0.6.0 |
Le mot-clé |
|
0.6.0 |
Fonctions sans implémentation en dehors d’un
doivent être marquées |
|
0.6.0 |
|
|
0.7.0 |
La syntaxe suivante est obsolète :
|
|
0.7.0 |
Le mot clé |
|
0.7.0 |
Supprime la visibilité des constructeurs. |
Veuillez lire 0.5.0 notes de mise à jour, 0.6.0 notes de mise à jour, 0.7.0 notes de mise à jour et 0.8.0 notes de mise à jour pour plus de détails.
Synopsis
Usage: solidity-upgrade [options] contract.sol
Allowed options:
--help Show help message and exit.
--version Show version and exit.
--allow-paths path(s)
Allow a given path for imports. A list of paths can be
supplied by separating them with a comma.
--ignore-missing Ignore missing files.
--modules module(s) Only activate a specific upgrade module. A list of
modules can be supplied by separating them with a comma.
--dry-run Apply changes in-memory only and don't write to input
file.
--verbose Print logs, errors and changes. Shortens output of
upgrade patches.
--unsafe Accept *unsafe* changes.
Rapports de bogue / Demandes de fonctionnalités
Si vous avez trouvé un bogue ou si vous avez une demande de fonctionnalité, veuillez déposer une question sur Github.
Exemple
Supposons que vous ayez le contrat suivant dans Source.sol
:
pragma solidity >=0.6.0 <0.6.4;
// Ceci ne compilera pas après la version 0.7.0.
// SPDX-License-Identifier: GPL-3.0
contract C {
// FIXME : supprimer la visibilité du constructeur et rendre le contrat abstrait.
constructor() internal {}
}
contract D {
uint time;
function f() public payable {
// FIXME : remplacer maintenant par block.timestamp
time = now;
}
}
contract E {
D d;
// FIXME : supprimer la visibilité du constructeur
constructor() public {}
function g() public {
// FIXME : change .value(5) => {value : 5}
d.f.value(5)();
}
}
Changements requis
Le contrat ci-dessus ne sera pas compilé à partir de la version 0.7.0. Pour mettre le contrat à jour avec la
version actuelle de Solidity, les modules de mise à jour suivants doivent être exécutés :
constructor-visibility
, now
et dotsyntax
. Veuillez lire la documentation sur
modules disponibles pour plus de détails.
Exécution de la mise à niveau
Il est recommandé de spécifier explicitement les modules de mise à niveau en utilisant l’argument --modules
.
solidity-upgrade --modules constructor-visibility,now,dotsyntax Source.sol
The command above applies all changes as shown below. Please review them carefully (the pragmas will have to be updated manually.)
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
abstract contract C {
// FIXME : supprimer la visibilité du constructeur et rendre le contrat abstrait.
constructor() {}
}
contract D {
uint time;
function f() public payable {
// FIXME : remplacer maintenant par block.timestamp
time = block.timestamp;
}
}
contract E {
D d;
// FIXME : supprimer la visibilité du constructeur
constructor() {}
function g() public {
// FIXME : change .value(5) => {value : 5}
d.f{value: 5}();
}
}
Comment cela fonctionne
Vous pouvez passer un ou plusieurs fichiers sources Solidity à
solidity-upgrade [files]
. Si ceux-ci utilisent l’instructionimport
qui fait référence à des fichiers en dehors du répertoire du fichier source actuel, vous devez spécifier des répertoires qui sont autorisés à lire et à importer des fichiers, en passant l’instruction--allow-paths [directory]
. Vous pouvez ignorer les fichiers manquants en passant--ignore-missing
.solidity-upgrade
est basé surlibsolidity
et peut analyser vos fichiers sources, et peut y trouver des mises à jour applicables.Les mises à jour de source sont considérées comme de petits changements textuels à votre code source. Elles sont appliquées à une représentation en mémoire des fichiers sources donnés. Le fichier source correspondant est mis à jour par défaut, mais vous pouvez passer la commande
--dry-run
pour simuler l’ensemble du processus de mise à jour sans écrire dans aucun fichier.Le processus de mise à jour lui-même a deux phases. Dans la première phase, les fichiers sources sont analysés, et puisqu’il n’est pas possible de mettre à jour le code source à ce niveau, les erreurs sont collectées et peuvent être enregistrées en passant
--verbose
. Aucune mise à jour de la source n’est disponible à ce stade.Dans la deuxième phase, toutes les sources sont compilées et tous les modules d’analyse de mise à niveau activés sont exécutés en même temps que la compilation. Par défaut, tous les modules disponibles sont activés. Veuillez lire la documentation sur les modules disponibles pour plus de détails.
Cela peut entraîner des erreurs de compilation qui peuvent être corrigées par des mises à jour des sources. Si aucune erreur ne se produit, aucune mise à niveau des sources n’est signalée et vous avez terminé. Si des erreurs se produisent et qu’un module de mise à niveau a signalé une mise à niveau de la source, la première source, la première signalée est appliquée et la compilation est déclenchée à nouveau pour tous les fichiers sources donnés. L’étape précédente est répétée aussi longtemps que des mises à jour de sources sont signalées. Si des erreurs surviennent encore, vous pouvez les enregistrer en passant le paramètre
--verbose
. Si aucune erreur ne se produit, vos contrats sont à jour et peuvent être compilés avec la dernière version du compilateur.