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,
}) => {
}
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.
export async function getContractTransactionCountScore({
chainId,
contractAddress,
}: IContractTransactionCountScore): Promise<ScoreResult> {
const url100 = getEtherscanContractTxsUrl({
txNumber: 100,
chainId,
contractAddress,
});
const { result: result100 } = await fetchUrl<EtherscanResponse>(url100);
if (result100.length === 1) {
return {
score: 3,
description: 'more than 100 txs',
};
}
const url50 = getEtherscanContractTxsUrl({
txNumber: 50,
chainId,
contractAddress,
});
const { result: result50 } = await fetchUrl<EtherscanResponse>(url50);
if (result50.length === 1) {
return {
score: 2,
description: 'more than 50 txs',
};
}
return {
score: 1,
description: 'fewer than 50 txs',
};
}
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.
const Weights = {
contractTransactionCountScore: 3,
contractAgeScore: 2,
contractVerificationScore: 1,
contractUserTransactionScore: 1,
};
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);
};
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 '🟥';
}
};
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
}`,
},
};
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 :
Consultez la documentation développeur
Installez MetaMask Flask
Consultez un guide MetaMask Snaps
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.