Passer de Solidity à Cairo

Initialement publié en anglais par StarkWare le 23 Juin, 2023

Guider les développeurs dans leur chemin vers la programmation en Cairo

TL;DR

  • Les développeurs élargissent leurs compétences pour inclure Cairo, motivé par la croissance de Starknet.

  • Solidity a permis la création de contrats intelligents interopérables à l'échelle mondiale, mais nécessitait une répétition importante des calculs.

  • L'efficacité de Cairo découle de sa capacité à créer des preuves d'exécution de transactions vérifiables à l'aide d'une seule machine.

  • Cairo et Solidity sont tous deux des langages de contrats intelligents, mais leurs fonctionnalités et leurs principes sont distincts.

Introduction

Avec la croissance de Starknet (et l'enthousiasme continu autour des Rollups), Cairo est devenu l'une des compétences les plus recherchées dans le domaine de la web3.

Cairo, est utilisé pour écrire des contrats intelligents sur Starknet et StarkEx, ainsi que pour mettre à l'échelle des applications telles que dYdX et ImmutableX. Le nombre de développeurs à temps plein a augmenté de manière spectaculaire de 875 % au cours des deux dernières années et de 83 % d'une année sur l'autre. Et comme Cairo peut être utilisé en dehors des blockchains chaque fois qu'une preuve de calcul est nécessaire, l'adoption de Cairo par les développeurs devrait continuer à augmenter.

Beaucoup de ces nouveaux développeurs Cairo proviennent de Solidity, le langage de contrats intelligents du L1. Si vous faites partie des développeurs qui effectuent cette transition, nous sommes là pour vous aider !

Dans cet article, nous vous donnerons un guide du développeur pour passer de Solidity à Cairo. Nous parlerons de ce qui distingue Cairo, de son fonctionnement d'un point de vue technique, puis nous examinerons quelques exemples de code pour montrer les principales différences entre les langages.

Commençons !

Qu’est-ce que Cairo?

Cairo est le langage de contrats intelligents natif pour Starknet et inspiré de Rust.

Selon la documentation de Cairo, "Cairo est le premier langage Turing-complet permettant de créer des programmes prouvables par STARK pour le calcul général." Analysons cette définition.

Turing-complet signifie que ce langage de programmation peut simuler une machine Turing-complet. Une machine Turing-complet (nommée d'après Alan Turing) est un ordinateur capable d'effectuer n'importe quelle computation et d'exécuter n'importe quel algorithme si suffisamment de temps et de ressources lui sont fournis.

Prouvable par STARK signifie que les programmes écrits en Cairo peuvent être exécutés de manière à ce qu'une preuve STARK (Scalable Transparent ARguments of Knowledge) de l'exécution puisse être créée efficacement. Lorsqu'un programme écrit en Cairo est exécuté sur n'importe quelle machine, une preuve STARK nouvellement générée est créée. Ceci permettant à tout Verifier indépendant de vérifier de manière succincte l'exécution honnête du programme, sans avoir à faire confiance à la machine sur laquelle les calculs du programme ont été effectués.

Cairo 1.0 vient d'être publié ce printemps (remplaçant Cairo 0) et est déjà disponible sur le Mainnet de Starknet.

Lequel est meilleur - Cairo ou Solidity ?

Aucun des deux ! D'une certaine manière, c'est une comparaison "entre pommes et oranges".

Solidity est le langage d'abord utilisé pour l'adoption généralisée de la computation composable. Un paradigme de programmation dans lequel différents composants d’un système peuvent être utilisés en synchronisation et composés en logiciels compliqués en utilisant différents composants comme des blocs Lego.

Solidity a permis aux contrats intelligents d'être étroitement liés pour les raisons suivantes :

  • Le bytecode est rendu public et transparent pour le monde

  • Les structures ABI standard (qui permettaient à d'autres d'interagir avec des contrats intelligents externes)

  • Mettez à profit le réseau Ethereum pour une disponibilité proche de 100%

  • L'utilisation du réseau Ethereum comme moyen d'exécuter des transactions financières

  • L'interopérabilité globale des contrats intelligents grâce à un EVM commun et unique (dont une copie est détenue par tous les validateurs du réseau)

Même si Solidity a atteint une myriade d’innovations en étant le langage de contrat intelligent le plus adopté, Cairo a une propriété unique et puissante : sa capacité à créer des programmes prouvables pour la computation générale.

Cette propriété fait une différence unique, nous permet de passer d'un système dans lequel chaque computation doit être répétée des centaines de milliers de fois (c'est le nombre de validateurs dans le réseau Ethereum), à un système plus récent où une seule machine (appelée Prover) crée une preuve de l'exécution correcte d'une transaction que d'autres sur le réseau peuvent vérifier.

Différences entre la machine virtuelle Cairo et la machine virtuelle Ethereum

Pour que l'exécution des programmes Cairo soit efficacement convertie en une preuve STARK, il existe quelques différences clés entre la machine virtuelle Cairo et la machine virtuelle Ethereum (EVM) :

  1. Modèle de mémoire : La machine virtuelle Cairo utilise un modèle de mémoire à écriture unique. Un emplacement mémoire ne peut pas être écrasé (contrairement à l'EVM). Bien que cela puisse sembler être une complexité importante, le compilateur Cairo résout ce problème, et la version abstraite permet l'utilisation de variables mutables dans le code (nous y reviendrons plus tard). Le modèle de mémoire à écriture unique rend Cairo plus prévisible et vérifiable. Chaque adresse mémoire est écrite une seule fois et conserve sa valeur jusqu'à ce que l'exécution du programme soit terminée. Cela signifie qu'il existe un enregistrement clair et immuable du calcul, ce qui est essentiel lors de la génération de preuves STARK, car elles reposent sur la vérification de la conformité des calculs.

  2. Champs (Fields) : Lorsque nous parlons de preuves cryptographiques, nous évoquons presque toujours la création de ces preuves pour des opérations sur des éléments d'un certain champ (field). Comme discuté dans notre article sur l'arithmétisation, en mathématiques, un champ est un ensemble d'éléments avec deux opérations binaires, l'addition et la multiplication. Il satisfait certains axiomes, tels que la clôture, l'associativité, la commutativité, et l'existence d'inverses et d'éléments d'identité. Les éléments d'un tel champ sont les sujets d'opérations qui font partie de n'importe quelle computation générale pouvant être prouvée. Lorsque l'on parle de champs, il est important de noter que certains champs sont finis (celui utilisé dans Cairo est également fini). Dans un champ fini, le nombre d'éléments est fini, et tous les éléments sont inférieurs à “l'ordre” le plus élevé du champ. “L'ordre” d'un champ équivaut au nombre le plus élevé que les éléments d'un champ peuvent atteindre plus un. De plus, toutes les opérations d'addition et de multiplication donnent un nombre, le module de l'ordre le plus élevé. Par exemple, dans un champ d'ordre 6, l'addition 3+4 donnerait comme résultat (3+4) mod 6 = 7 mod 6 = 1. Cairo utilise un champ fini d'ordre 2²⁵¹ + 17 * 2¹⁹² + 1. Puisque, lors de la génération de preuves, tous les éléments doivent être des éléments de champ, la machine virtuelle Cairo utilise des éléments de champ comme base pour toutes les opérations. Elle ne suit pas le système conventionnel uint256 ou uint32 utilisé par l'EVM. Cependant, des techniques d'abstraction peuvent être créées pour utiliser le type uint256 (ou similaire) plus pratique. Néanmoins, ces structures nécessitent plus de ressources (augmentation du nombre d'opérations pour prouver la même chose de l'ordre de dizaines) lors de l'exécution.

  3. Héritage et polymorphisme : Cairo n'a pas les concepts d'héritage et de polymorphisme. Bien que les contrats puissent être étendus en important des fonctions et des variables de stockage spécifiques, les concepts très utilisés de la programmation orientée objet nécessitent une réflexion un peu différente.

Cairo se compile en Sierra

Une étape à noter est que lorsque vous rédigez un smart contrat Cairo, il est d'abord converti en code Sierra, qui doit être publié sur le réseau. Le code Sierra est une abstraction du code assembleur Cairo brut (CASM) interprété par la machine virtuelle Cairo. La compilation du code Cairo en code Sierra entoure le code Cairo de certaines mesures de sécurité, la plus importante étant un mécanisme pour éviter les attaques DoS.

Selon la documentation de Starknet, "Une propriété cruciale de chaque L2 décentralisée est que les séquenceurs sont garantis d'être rémunérés pour le travail qu'ils accomplissent. La notion de transactions révoquées en est un bon exemple : même si la transaction de l'utilisateur a échoué en cours d'exécution, le séquenceur devrait pouvoir l'inclure dans un bloc et facturer des frais d'exécution jusqu'au point d'échec."

Cependant, parfois, un utilisateur peut écrire une ligne de code ou inclure une transaction, prouvant que l'exécution est impossible. Par exemple, l'instruction assert 1 == 0 est une instruction Cairo valide ; cependant, inclure cette exécution dans une preuve cryptographique n'est pas possible car cette instruction est fausse, et elle se traduit par des contraintes polynomiales qui ne sont pas satisfaisables. Par conséquent, Sierra ajoute une couche de sécurité qui garantit que même les transactions révoquées impossibles à prouver sont facturées. Cela atténue à la fois le potentiel d'une attaque DoS contre le séquenceur et répond aux incitations économiques du séquenceur.

Comparaison entre Cairo et Solidity

Maintenant, nous avons une idée des types, fonctions et structures de base de Cairo. Comparons-les à leurs homologues en Solidity pour établir quelques parallèles entre les deux langages de smart contrat. (Gardez à l'esprit que Cairo peut également être utilisé pour écrire du code non lié aux smart contrats pouvant être utilisé pour créer des programmes vérifiables. Cependant, cela sort du cadre de notre discussion actuelle.)

Note : À partir de ce point, toute discussion concernant Cairo concerne Cairo 1. Cairo 0 n'est plus recommandé comme langage de choix pour écrire des smart contrats sur Starknet.

Types de Cairo

Voici la liste de quelques types fondamentaux en Cairo :

Comme vous pouvez le voir dans la liste ci-dessus (nous venons d'ajouter les nombres entiers signés et nous avons également Dict.) À partir de Cairo 1, les nombres entiers non signés ont été ajoutés à Cairo, similaires à leurs homologues en Solidity. Bien que l'utilisation d'entiers puisse être moins rentable pour le séquenceur que l'utilisation directe de felts, l'intégration des entiers dans Cairo promet de simplifier la vie des développeurs.

Mis à part cela, l'utilisation des tableaux est très similaire à la syntaxe en Rust, et leur logique est similaire à celle de Solidity.

Fonctions en Cairo

Les fonctions en Cairo peuvent être de types suivants :

  • interne

  • externe

  • vue

  • constructeur

Par défaut, toutes les fonctions de contrat sont considérées comme interne (de telles fonctions ne peuvent être appelées que depuis l'intérieur du contrat, quelque peu similaires aux fonctions privées dans d'autres langages).

Les fonctions externes sont ouvertes au monde et peuvent être appelées par d'autres smart contracts, y compris les comptes. (Hourra, abstraction de compte !)

Les fonctions de vue sont un type de fonction externe qui ne peut lire que l'état on-chain. Les fonctions de vue ne peuvent pas modifier l'état de la chaîne.

Le constructeur est un autre attribut des fonctions en Cairo donné aux... constructeurs d'un smart contrat !

Maintenant, comparons la syntaxe de déclaration de fonction entre Cairo et Solidity :

Penchons-nous plus en détail sur quelques différences clés :

  1. Le mot-clé pour déclarer une fonction est fn dans Cairo, tandis qu’avec Solidity, c'est function.

  2. Les types de fonctions sont déclarés avant le mot-clé de la fonction avec Cairo (#[view]), mais pour Solidity, le format est différent (voir ci-dessus).

  3. Dans le langage de programmation Cairo, la syntaxe pour déclarer les valeurs de retour implique l'utilisation du symbole . En revanche, avec Solidity, le mot-clé returns est utilisé pour indiquer les valeurs de retour.

Modules dans Cairo

Les modules dans Cairo servent à regrouper des fonctionnalités connexes dans un namespace. Le mot-clé mod est utilisé pour définir un module, suivi du nom du module et d'un bloc de code qui comprend des fonctions et d'autres déclarations. Les modules peuvent importer d'autres modules et utiliser leur fonctionnalité.

Ces modules sont similaires aux bibliothèques dans d'autres langages, et avec Solidity, les modules peuvent être comparés à l'héritage des contrats.

Par exemple, dans le code ci-dessus, les modules starknet et array sont importés. La syntaxe diffère des déclarations import avec Solidity ou de l'héritage qui utilise le mot-clé is (voir ceci). Notez que le mot-clé use rend toutes les fonctions du module importé accessibles à l'intérieur du module d'importation avec Cairo.

Tableaux en Cairo

L'utilisation des tableaux avec Cairo 1.0 est devenue plus simple, car les manipulations du tableau dynamique sont rendues possibles avec les fonctions exportées du module de tableau, telles que append, array_at, et array_len.

Exemple de contrat intelligent avec Cairo

Maintenant que nous comprenons l'ensemble des types et des fonctions en Cairo, examinons un exemple de code de contrat intelligent ERC20 avec Cairo. Un contrat ERC20 est un modèle de contrat intelligent standard pour les tokens que les utilisateurs détiennent on-chain. Il permet aux utilisateurs de transférer des tokens entre eux, de vérifier les soldes des utilisateurs et d'approuver les transferts vers une autre entité. Voici notre contrat :

Remarque : La syntaxe de Cairo 1 change légèrement et sera mise à jour plus tard cette année (2023). Veuillez consulter ce billet pour plus de détails.

Le code ci-dessus est basé sur https://github.com/argentlabs/starknet-build/blob/main/cairo1.0/examples/erc20/ERC20.cairo

Examinons en détail certaines des parties les plus importantes.

Les lignes 1 et 2 initialisent et donnent le nom au smart contract

#[contract]

mod ERC20 {

La ligne 4 importe la fonction get_caller_address depuis le module starknet. La fonction get_caller_address() renvoie l'adresse du contrat qui a appelé la fonction.

use starknet::get_caller_address;

Les lignes 7 à 14 définissent une structure (similaire à struct en Solidity) qui est utilisée plus tard dans le code.

Les lignes 20 et 21 définissent un événement Transfer qui est émis chaque fois que le jeton ERC20 est transféré. Les événements constituent un moyen efficace de suivre les activités de contract/les changements d'état, permettant ainsi aux auditeurs externes de réagir en conséquence.

#[event]

fn Transfer(from_: felt, to: felt, value: u256) {}

Les lignes 36 à 54 contiennent une fonction constructeur (la fonction appelée lorsque le contrat est déployé) et une fonction d'affichage qui lit la variable de stockage name et renvoie sa valeur à l'utilisateur.

Les lignes 97 à 101 définissent une fonction externe (comme discuté précédemment) qui est utilisée pour transférer des jetons ERC20 d'un compte à un autre. Cette fonction appelle la fonction transfer_helper() en dessous, qui émet également l'événement Transfer() défini ci-dessus.

Conclusion

Si vous êtes à l'aise avec Solidity, vous devriez maintenant avoir une excellente base pour comprendre comment fonctionne Starknet, les différences entre Cairo et Solidity, et comment lire des contrats intelligents Cairo de base.

Pour la prochaine étape de votre parcours de développement Cairo, consultez la documentation de Cairo, inscrivez-vous à Cairo Basecamp ou suivez les tutoriels.

Subscribe to Starknet France
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.