Trust Score Snap : simplifier les transactions grâce aux couleurs de code

Lauréat du Hackathon ETHLisbon

8 min de lecture
Trust Score Snap : simplifier les transactions grâce aux couleurs de code

MetaMask Snaps est la feuille de route pour faire de MetaMask le wallet le plus extensible au monde. En tant que développeur, vous pouvez intégrer vos fonctionnalités et vos API à MetaMask de manières totalement nouvelles. Les développeurs Web3 sont au cœur de cette croissance, et cette série vise à mettre en lumière les MetaMask Snaps innovants en cours de développement.

Trust Score Snap

Dépôt du Snap : https://github.com/Tbaut/template-snap-monorepo

Pourquoi l'avez-vous créé ?

En matière de signature de transactions sur Ethereum, le problème majeur que tout le monde évite d'aborder est que la plupart des utilisateurs n'ont aucune idée de ce qu'ils signent. Décoder les méthodes et les arguments est un bon premier pas, mais si les utilisateurs interagissent avec un contrat malveillant, les informations affichées peuvent être trompeuses. Pour contrebalancer cela, j'ai pensé à afficher des données quantitatives, de manière très simple, en utilisant des codes couleur 🟥 🟧 🟩. L'idée est d'afficher un score de confiance basé sur des données faciles à vérifier depuis plusieurs sources. J'ai choisi de commencer avec 4 critères :

  • Combien d'utilisateurs ont interagi avec le smart contract au total.

  • À quelle fréquence le compte actuel a interagi avec ce contrat.

  • Depuis combien de temps ce contrat existe.

  • Le code de ce contrat a-t-il été vérifié.

Pouvez-vous nous expliquer l'implémentation technique ?

La fonction principale des insights

Le snap est très simple et facile à étendre. Voici le code complet que nous allons parcourir.

Lorsque l'onglet insights est cliqué dans MetaMask, la fonction onTransaction est appelée. À l'intérieur, nous appelons chaque fonction nous fournissant les critères que nous avons décidé de prendre en compte.

type ScoreResult = {
  score: number;
  description: string;
};

const onTransaction: OnTransactionHandler = async ({
  transaction,
  chainId,
}) => {
  // call all the insights criteria
  // they all return a ScoreResult
}
Copier

Ces fonctions appellent généralement une API et traitent les résultats. Examinons l'une d'elles pour mieux comprendre.

Déterminer un score de confiance basé sur les interactions globales

Examinons la fonction qui attribue un score basé sur le nombre total de transactions reçues par un contrat. Nous utilisons ici l'API Etherscan, mais n'importe quelle autre API pourrait fonctionner pour vérifier les mêmes données.

/**
 * Gets a trust score for a contract based on the overall tx count
 * 3 -> the contract had overall >=100 txs
 * 2 -> the contract had overall 50 <= tx < 99
 * 1 -> the contract had overall tx < 50
 *
 *@param options0
 * @param options0.chainId - the chain id to call the api with
 * @param options0.contractAddress - the contract address to check
 * @returns the score and a description
 */
export async function getContractTransactionCountScore({
  chainId,
  contractAddress,
}: IContractTransactionCountScore): Promise<ScoreResult> {
  // get the api url asking for the 100th transaction
  // it will return undefined if there is none
  const url100 = getEtherscanContractTxsUrl({
    txNumber: 100,
    chainId,
    contractAddress,
  });
  const { result: result100 } = await fetchUrl<EtherscanResponse>(url100);

  // if there is a 100th tx it means the contract
  // has received at least 100 txs. We have all we need
  // we can return with the best score of 3
  if (result100.length === 1) {
    return {
      score: 3,
      description: 'more than 100 txs',
    };
  }

  // this will be call if there are less than 100 txs
  // we check if there is a 50th tx.
  const url50 = getEtherscanContractTxsUrl({
    txNumber: 50,
    chainId,
    contractAddress,
  });
  const { result: result50 } = await fetchUrl<EtherscanResponse>(url50);

  // if there is a 50th tx we can return with a score of 2
  if (result50.length === 1) {
    return {
      score: 2,
      description: 'more than 50 txs',
    };
  }

  // otherwise, return with the lowest score
  return {
    score: 1,
    description: 'fewer than 50 txs',
  };
}
Copier

Tous les scores ne sont pas égaux

Maintenant que nous avons un TrustResult pour chacun de nos critères, il est temps d'appliquer des pondérations. En effet, le score de confiance de chacun de nos critères ne devrait pas avoir le même poids. Par exemple, le nombre de transactions passées avec le contrat a un coût. Si un escroc voulait le manipuler, cela lui coûterait de l'ETH en frais de gas. Par conséquent, ce critère est considéré comme plus coûteux à manipuler, donc plus important — je lui ai attribué un poids de 3.

De même, l'ancienneté du contrat ne peut pas être contournée par un attaquant : il devrait le déployer, puis attendre avant de lancer son attaque s'il voulait obtenir un score de confiance élevé. Je lui ai attribué un poids de 2.

Les autres critères sont considérés comme moins robustes et ont un poids de 1.

// arbitrary weight for each score
const Weights = {
  contractTransactionCountScore: 3,
  contractAgeScore: 2,
  contractVerificationScore: 1,
  contractUserTransactionScore: 1,
};

// calculate the overall trust score after applying the weights
const calculateOverallScoreWithWeight = ({
  contractTransactionCountScore,
  contractUserTransactionScore,
  contractAgeScore,
  contractVerificationScore,
}: CalculateOverallScoreWithWeightArgs) => {
  const totalWeitght = Object.values(Weights).reduce(
    (acc: number, curr: number) => acc + curr,
    0,
  );

  const overallScoreWithWeight =
    (contractUserTransactionScore.score * Weights.contractUserTransactionScore +
      contractTransactionCountScore.score *
        Weights.contractTransactionCountScore +
      contractAgeScore.score * Weights.contractAgeScore +
      contractVerificationScore.score * Weights.contractVerificationScore) /
    totalWeitght;

  return Math.floor(overallScoreWithWeight);
};
Copier

Présenter le score final

Enfin, maintenant que nous avons le score de confiance d'un smart contract, nous devons l'afficher de manière simple. L'API insights de MetaMask permet uniquement d'afficher des paires clé-valeur. Les clés sont en gras, et les valeurs ont une graisse de police normale. J'ai pensé qu'en utilisant des emojis, je pourrais créer une interface qui n'intimide pas les utilisateurs, tout en affichant toutes les informations collectées.

La fonction transformant le score de confiance en emojis :

const getColor = (result: number) => {
  switch (result) {
    case 3:
      return '🟩';
    case 2:
      return '🟧';
    default:
      return '🟥';
  }
};
Copier

Et la partie retour de la fonction onTransaction, avec quelques astuces pour afficher les paires clé-valeur de manière élégante :

return {
    insights: {
      '': `Trust score: ${getColor(overallScore)}`,
      ' ': '-----------------------------',
      'Contract popularity': `${getColor(
        contractTransactionCountScore.score,
      )} ${contractTransactionCountScore.description}`,
      'Previous interactions': `${getColor(
        contractUserTransactionScore.score,
      )} ${contractUserTransactionScore.description}`,
      'Contract age': `${getColor(contractAgeScore.score)} ${
        contractAgeScore.description
      }`,
      'Contract verification': `${getColor(contractVerificationScore.score)} ${
        contractVerificationScore.description
      }`,
    },
  };
Copier

Enfin, j'ai créé une interface très simple pour appeler 2 types de contrats : un contrat Uniswap très connu et largement utilisé, et un contrat de stockage très récemment déployé, celui présenté par défaut sur Remix. Si vous utilisiez ce snap et interagissiez avec le contrat router Uniswap, vous verriez ce qui suit :

Quelles seraient les prochaines étapes si vous deviez l'implémenter ?

Ce n'est qu'effleurer la surface des informations qui pourraient donner confiance aux utilisateurs ou les protéger contre le phishing. La première étape évidente serait d'utiliser davantage de sources pour nos données. La vérification du contrat utilise déjà Sourcify et Etherscan, mais il serait préférable d'utiliser plusieurs sources pour chaque critère.

Ensuite, nous devrions appliquer des algorithmes plus avancés pour empêcher les escrocs de manipuler facilement les scores. Par exemple, nous devrions compter le nombre de comptes uniques ayant effectué des transactions avec un contrat. Nous pourrions également effectuer une analyse des comptes ayant interagi avec lui dans le passé, afin de s'assurer qu'ils ne proviennent pas tous d'une même source. L'inconvénient est que toute cette analyse est plus difficile à réaliser en utilisant plusieurs sources de vérité.

Des recherches intéressantes ont également été menées sur la détection des arnaques liées aux smart contracts, qui pourraient être intégrées. Plus d'informations ici.

Dans l'ensemble, le nombre écrasant de réactions positives que j'ai reçues pour ce hack montre que les utilisateurs réclament davantage d'informations, et je crois que la facilité de compréhension a joué un rôle clé.

Pouvez-vous nous parler un peu de vous ?

Je suis ingénieur logiciel chez ChainSafe et j'ai travaillé chez Parity par le passé. J'aime créer des produits en mettant l'accent sur une bonne expérience utilisateur. Le Web3 est un excellent terrain de jeu pour moi, car tout est si complexe que tenter de le rendre compréhensible au plus grand nombre est un vrai défi. Je suis dans cet écosystème depuis presque 5 ans et, bien que j'aie participé à de nombreux hackathons, je suis généralement bénévole, mentor ou juge plutôt que participant. La principale raison est que je suis perfectionniste et que je n'aime généralement pas les solutions rapides et approximatives :).

Quand avez-vous découvert MetaMask Snaps pour la première fois et quelle a été votre expérience ?

Fait intéressant, mes collègues de ChainSafe ont créé l'un des tout premiers snaps, celui pour Filecoin. J'avais probablement jeté un œil au code à l'époque, mais je n'avais pas approfondi.

Au moment du hackathon, l'API insights n'était pas encore disponible pour les développeurs. Je discutais avec l'équipe MetaMask à Lisbonne et je ne m'attendais pas à pouvoir ajouter une interface utilisateur à MetaMask. Ils m'ont dit qu'elle était sur le point d'être publiée et que je pouvais déjà commencer à développer dessus. En réalité, cela n'était disponible qu'avec un build personnalisé, et la documentation n'avait pas encore été publiée.

En quoi MetaMask Snaps se distingue-t-il des autres wallets ?

La possibilité d'ajouter du code personnalisé dans un onglet, tout en s'assurant que ce code est sûr à exécuter, ouvre la porte à un large éventail d'améliorations. J'ai vraiment hâte de voir ce qui en découlera.

Parlez-nous de votre expérience de développement de Snaps avec MetaMask.

Le monorepo template a rendu le démarrage très facile. Le fait que tout mon code puisse être écrit dans un seul dépôt, avec une seule commande pour lancer à la fois la dapp de test et le snap, tous deux avec rechargement automatique, a été une excellente expérience développeur.

Que représentent les Snaps pour vous ?

C'est l'extension d'une extension. Aucun produit ne peut convenir à tous les utilisateurs. Ajouter cette couche composable est une formidable opportunité pour quiconque souhaite développer une fonctionnalité dont il a besoin.

Quelles opportunités voyez-vous avec MetaMask Snaps et les possibilités qu'ils ouvrent pour l'écosystème Web3 ?

Je vais parler en particulier des insights, qui offrent une personnalisation infinie selon les besoins. Je parie que de nombreux autres insights liés à la sécurité seront développés à l'avenir.

Avez-vous des conseils à partager avec les développeurs souhaitant essayer MetaMask Snaps ?

Clonez le monorepo et profitez d'un démarrage ultra-rapide.

Développer avec MetaMask Snaps

Pour commencer avec MetaMask Snaps :

  1. Consultez la documentation développeur

  2. Installez MetaMask Flask

  3. Consultez un guide MetaMask Snaps

  4. Restez connecté avec nous sur Twitter, les discussions GitHub et Discord

Gardez un œil sur notre équipe lors du prochain hackathon près de chez vous ! Bon BUIDLing ⚒️

Avertissement : Les MetaMask Snaps sont généralement développés par des tiers autres que Consensys Software. L'utilisation de MetaMask Snaps développés par des tiers se fait à votre propre discrétion et à vos propres risques, et implique votre accord selon lequel vous serez seul responsable de toute perte ou dommage résultant de ces activités. Consensys ne fournit aucune garantie expresse ou implicite, qu'elle soit orale ou écrite, concernant les MetaMask Snaps développés par des tiers, et décline toute responsabilité pour les Snaps développés par des tiers. L'utilisation de logiciels liés à la blockchain comporte des risques que vous assumez entièrement lors de l'utilisation de MetaMask Snaps.

Traduit par IA. Peut contenir des erreurs. Veuillez toujours vérifier les informations.

Évaluer la traduction
  • MetaMask
    MetaMask

    MetaMask, anciennement Consensys Software Inc, est la plus grande plateforme financière self-custodial au monde, offrant aux utilisateurs un espace unique pour détenir, dépenser, épargner et faire fructifier leur argent, aussi bien en crypto qu'en actifs traditionnels. L'entreprise développe la plateforme grand public où tout cela se concrétise, réunissant paiements, épargne, investissement et actifs numériques en une expérience fluide et unifiée. Forte de sa croissance en tant que wallet self-custodial le plus utilisé au monde, MetaMask donne aux utilisateurs un contrôle direct sur leur argent et leurs actifs, avec une présence dans environ 190 pays. MetaMask joue un rôle fondateur dans la croissance d'Ethereum depuis 2016. Aujourd'hui, MetaMask se trouve au cœur de l'économie onchain, en construisant le système d'exploitation de l'Open Money et en donnant aux individus un contrôle total sur leur vie financière.

    Lire tous les articles