Titres Titres

Suite à la partie 3 : tests d’intrusion, cet article présente les éléments internes d’Anchor, un cadre populaire pour écrire et tester les contrats intelligents Solana.
A l’instar de Truffle pour Ethereum, Anchor propose un panel de fonctionnalités permettant de développer une application complète sur Solana, notamment :
Nous allons détailler le internes de l’ancre et quelques mises en garde du point de vue d’un auditeur.
L’ancre expose un modèle de programmation déclaratif où un utilisateur peut annoter des méthodes ou des types de données (structs et leurs champs) en utilisant macro, qui alors générer automatiquement des wrappers de code à exécuter sur Solana.
Les wrappers de code générés peuvent faire une variété de choses, telles que décoder les données d’entrée, créer et initialiser des comptes, et plus important encore, assurer des contraintes supplémentaires sur les données d’entrée, par exemple, l’application d’un compte d’entrée est le signataire et les relations entre plusieurs comptes d’entrée.
Il existe trois macros Anchor couramment utilisées :
- #[program] — instructions globales déclarées à l’intérieur de #[program]
- #[derive(Accounts)] — structs désérialisés en tant que vecteur de comptes d’entrée
- #[account(…)] — contraintes associées à chaque champ de structure, c’est-à-dire à chaque compte d’entrée
Ensuite, nous utiliserons un exemple (basic-2 fourni dans Anchor) pour illustrer en détail chacune des trois macros ci-dessus et leur code généré.
Il existe également un certain nombre d’autres macros Anchor, telles que `#[state]` (méthodes d’état), `#[interface]` (méthodes d’interface), etc. Une liste d’entre elles peut être trouvée dans Anchor CHANGELOG.
1. #[program] — instructions globales
Dans un programme Solana standard sans ancre, il y aura un point d’entrée (défini par point d’accès! macro), et il y a trois paramètres passés au point d’entrée : id_programme, comptes, et données_instruction. Pour invoquer une instruction correspondante, le le programme doit analyser le fichier instruction_data.
Cependant, avec Anchor, il n’est pas nécessaire de spécifier un point d’entrée ou d’analyser instruction_data. Tout est géré par le `#[program]` macro.
La figure 1 montre les deux fonctions (créer au ligne 9 et incrément ligne 16) : ce sont des instructions contractuelles qui seront invoquées par les transactions. Avec le `#[program]` macro (ligne 5), Anchor générera le code suivant pour appeler ces instructions (utilisez cargo expand
pour afficher le résultat de l’expansion de la macro):
La fonction de point d’entrée utilisera solana_program::entrypoint::deserializ à décoder l’entrée dans un tuple (id_programme, comptes, données_instruction), et appelez une autre fonction « entry », qui appelle ensuite la fonction « dispatch » en prenant le tuple comme paramètres (similaire à instruction_processus):
Dans la figure 4, la fonction de répartition utilise les 8 premiers octets des données d’instruction (appelées « soupir”) pour identifier l’instruction appelée. Si soupir correspond à une instruction définie par l’utilisateur, le wrapper de gestionnaire de méthode correspondant sera invoqué. Par exemple, [24, 30, 200, 40, 5, 28, 7, 119] Correspond à « __global::create » et [11, 18, 104, 9, 104, 174, 59, 33] Correspond à « __global::increment”.
Les wrappers de gestionnaire de méthode dans notre exemple sont définis ci-dessous :
Les emballages (__global :: créer et __global::increment) enveloppez les instructions correspondantes (basic_2:créer et basic_2:incrémenter), désérialiser les comptes, construire le contexte, invoquer le code de l’utilisateur et enfin exécuter la routine de sortie, qui persiste généralement les modifications de compte.
2. #[derive(Accounts)] — désérialisation des comptes
Pour chaque structure T marqué avec #[derive(Accounts)] , Anchor générera une fonction correspondante T::try_accounts cette désérialise les comptes d’entrée et ajoute des contrôles de validation.
Par exemple, dans la figure 6, #[derive(Accounts)] est déclaré au-dessus des deux structs Créer et Incrément. Cela indique à Anchor de générer deux try_accounts les fonctions (Créer::try_accounts et Incrémenter::try_accounts), qui désérialisera les comptes d’entrée en ctx.comptes, comme montré dans Figure 5 .
Notez que les premiers paramètres des instructions du contrat sont tous `ctx`, de type paramétrique `Contexte
La figure 7 montre la définition de « Context », une structure qui encapsule trois champs : id_programme, comptes, et comptes_restants. Noter: tandis que comptes sont désérialisés et validés selon les macros, comptes_restants ne le sont pas, son utilisation doit donc être très prudente.
3. #[account(…)] — les logiques et contraintes de désérialisation
Les logiques de désérialisation des champs de la struct sont spécifiées par #[account(…)], où … désigne une liste d’attributs, tels que mut
, init
, owner=…
, has_one=…
, payer=…
etc.
Chaque attribut dénote une certaine contrainte pour le compte correspondant, et les contrôles des contraintes sont automatiquement ajoutés dans try_accounts. Par example:
mut
ajoute un chèque pour est_inscriptibleinit
crée un compte et l’initialisepayer=user
définit le compte utilisateur comme payeur pour le compte init
La figure 8 montre le Increment.try_accounts
une fonction. Prendre en compte #[account(mut, has_one = authority)] macro déclarée sur le compte compteur :
#[account(mut, has_one = authority)]
pub counter: Account<'info, Counter>,
pub authority: Signer<'info>,
Pour l’attribut mut
, il génère le contrôle :
Pour l’attribut has_one=authority
, il génère le contrôle :
has_one=authority
: applique la contrainte quiIncrement.counter.authority == Increment.authority.key
.
Il existe également des types de compte intégrés tels que Signataire (Chèque est_signataire pour le compte) et Programme (la programme_système).
De plus, Anchor génère également exonération de loyer chèques pour tous les comptes marqués d’un #[account(init)]
par défaut (sauf si rent_exempt = sauter):
Dans l’ensemble, grâce à un modèle de programmation déclaratif, Anchor facilite beaucoup l’écriture de contrats intelligents Solana par rapport aux programmes Rust natifs. Cependant, il y a quelques mises en garde à noter :
- Anchor est toujours en cours de développement, donc les caractéristiques et la sémantique de certaines macros peut être sujet à changement.
- L’ancre n’a pas été auditée, tout bogue dans Anchor codegen peut conduire à des vulnérabilités subtiles inaperçues.
- Les contraintes déclaratives dans
#[account(...)]
doit faire l’objet d’une attention particulière pour assurer une validation suffisante et un contrôle d’accès correct de chaque instruction contractuelle. - Soyez très prudent lorsque vous utilisez
ctx.remaining_accounts
directement. Les comptes restants dans la structure Context ne sont ni désérialisés ni validés.
Soteria est fondée par des esprits de premier plan dans les domaines de la sécurité blockchain et de la vérification logicielle.
Nous sommes ravis de fournir des services d’audit aux Dapps à fort impact sur Solana. Veuillez visiter soteria.dev ou envoyer un courriel contact@soteria.dev
Comment auditer les séries de contrats intelligents Solana ?
Pour tous les blogs de Soteria, veuillez visiter https://blog.soteria.dev/
Rejoignez Coinmonks Telegram Channel et Youtube Channel pour en savoir plus sur le trading et l’investissement crypto