Les + populaires

BTC ETH SOL XRP BNB USDC USDT

Suivez-nous

Comment auditer les contrats intelligents Solana Partie 4 : le cadre Anchor | par Soteria | Coinmoines | déc. 2021

IAavec
Titres Titres
Soteria

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.

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.

Figure 1. #[program] macro en basic-2

1. #[program] — instructions globales

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):

Figure 2. point d’entrée généré par Anchor

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):

Figure 3. fonction de saisie générée par Anchor
Figure 4. fonction de répartition générée par Anchor

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 :

Figure 5. wrappers de gestionnaire de méthode générés par Anchor

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.

Figure 6. #[derive(Accounts)] et #[account(…)] macros en basic-2

2. #[derive(Accounts)] — désérialisation des comptes

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`. Dans la figure 1 (l’exemple basic_2 ), `Contexte` et `Contexte` respectivement .

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.

Figure 7. la structure « Context » définie dans Anchor

3. #[account(…)] — les logiques et contraintes de désérialisation

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_inscriptible
  • init crée un compte et l’initialise
  • payer=user définit le compte utilisateur comme payeur pour le compte init
Figure 8. la fonction Increment::try_accounts générée par Anchor

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 qui Increment.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):

  1. Anchor est toujours en cours de développement, donc les caractéristiques et la sémantique de certaines macros peut être sujet à changement.
  2. L’ancre n’a pas été auditée, tout bogue dans Anchor codegen peut conduire à des vulnérabilités subtiles inaperçues.
  3. 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.
  4. 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.

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

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

Lire aussi

Source medium.com

Optimisez vos coûts bancaires
Revolut
Profitez d'abonnements gratuits

Donnez votre avis

Soyez le 1er à noter cet article


Partagez cet article maintenant !

Envoyez simplement nos contenus crypto et finance à vos proches.