Trust Score Snap: Transaktionen durch Farbcodes vereinfachen

Ein ETHLisbon Hackathon-Gewinner

8 Min. Lesezeit
Trust Score Snap: Transaktionen durch Farbcodes vereinfachen

MetaMask Snaps ist der Fahrplan, um MetaMask zur erweiterbarsten Wallet der Welt zu machen. Als Entwickler kannst du MetaMask auf völlig neue Weise mit deinen Features und APIs bereichern. Web3-Entwickler sind das Herzstück dieses Wachstums, und diese Serie soll die innovativen MetaMask Snaps vorstellen, die heute entwickelt werden.

Trust Score Snap

Snap-Repository: https://github.com/Tbaut/template-snap-monorepo

Warum hast du es gebaut?

Beim Signieren von Transaktionen auf Ethereum ist das offensichtliche Problem, dass die meisten Nutzer kaum wissen, was sie da eigentlich unterschreiben. Das Dekodieren von Methoden und Argumenten ist ein guter erster Schritt – doch wenn Nutzer mit einem bösartigen Contract interagieren, können die angezeigten Informationen irreführend sein. Um dem entgegenzuwirken, dachte ich daran, quantitative Daten auf sehr einfache Weise mithilfe von Ampelfarben darzustellen 🟥 🟧 🟩. Die Idee ist, einen Trust Score auf Basis von Daten anzuzeigen, die sich leicht aus mehreren Quellen verifizieren lassen. Ich habe mich für 4 Kriterien entschieden:

  • Wie viele Nutzer insgesamt mit dem Smart Contract interagiert haben.

  • Wie oft das aktuelle Konto mit diesem Contract interagiert hat.

  • Wie alt dieser Contract ist.

  • Ob der Code dieses Contracts verifiziert wurde.

Kannst du uns durch die technische Umsetzung führen?

Die zentrale Insights-Funktion

Der Snap ist sehr einfach aufgebaut und lässt sich leicht erweitern. Hier ist der vollständige Code, den wir uns gemeinsam ansehen werden.

Wenn der Insights-Tab in MetaMask angeklickt wird, wird die Funktion onTransaction aufgerufen. Darin rufen wir jede Funktion auf, die uns die Kriterien liefert, die wir berücksichtigen wollen.

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

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

Diese Funktionen rufen in der Regel eine API auf und verarbeiten die Ergebnisse. Schauen wir uns eine davon genauer an.

Einen Trust Score auf Basis der Gesamtinteraktionen ermitteln

Sehen wir uns die Funktion an, die einen Score basierend auf der Gesamtanzahl der Transaktionen berechnet, die ein Contract erhalten hat. Wir verwenden hier die Etherscan-API, aber jede andere API könnte dieselben Daten verifizieren.

/**
 * 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',
  };
}
Kopieren

Nicht alle Scores sind gleich

Jetzt, da wir für jedes unserer Kriterien ein TrustResult haben, ist es an der Zeit, Gewichtungen anzuwenden. Tatsächlich sollte nicht jeder Trust Score der einzelnen Kriterien gleich gewichtet werden. Beispielsweise ist die Anzahl vergangener Transaktionen mit dem Contract mit Kosten verbunden. Wenn ein Betrüger versuchen würde, diesen Wert zu manipulieren, würde ihn das ETH für Gas kosten. Daher gilt dieses Kriterium als schwerer zu manipulieren und damit wichtiger – ich habe ihm eine Gewichtung von 3 gegeben.

Ebenso kann das Alter des Contracts von einem Angreifer nicht umgangen werden: Er müsste ihn deployen und dann warten, bevor er seinen Angriff startet, wenn er einen hohen Trust Score erzielen wollte. Ich habe ihm eine Gewichtung von 2 gegeben.

Die anderen Kriterien gelten als schwächer und haben eine Gewichtung von 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);
};
Kopieren

Den finalen Score präsentieren

Jetzt haben wir den Trust Score eines Smart Contracts und müssen ihn auf einfache Weise darstellen. Die MetaMask Insights API erlaubt es nur, Schlüssel-Wert-Paare anzuzeigen. Die Schlüssel sind fett gedruckt, und die Werte haben eine normale Schriftstärke. Ich dachte mir, dass ich durch den Einsatz von Emojis eine Oberfläche schaffen kann, die Nutzer nicht überfordert und dennoch alle gesammelten Informationen zeigt.

Die Funktion, die den Trust Score in Emojis umwandelt:

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

Und der Rückgabeteil der onTransaction-Funktion mit einigen Kniffen, um Schlüssel-Wert-Paare ansprechend darzustellen:

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
      }`,
    },
  };
Kopieren

Schließlich habe ich eine sehr einfache Oberfläche erstellt, um 2 Arten von Contracts aufzurufen: einen sehr bekannten und viel genutzten Uniswap-Contract und einen sehr kürzlich deployten Storage-Contract – denjenigen, der standardmäßig auf Remix angezeigt wird. Wenn du diesen Snap verwendest und mit dem Uniswap-Router-Contract interagierst, würdest du Folgendes sehen:

Was wären die nächsten Schritte, wenn du das weiterentwickeln würdest?

Das kratzt nur an der Oberfläche dessen, welche Informationen Nutzern Vertrauen geben oder sie vor Phishing schützen könnten. Der naheliegende erste Schritt wäre, mehr Quellen für unsere Daten zu nutzen. Die Contract-Verifizierung verwendet bereits Sourcify und Etherscan, aber es wäre besser, für jedes Kriterium mehrere Quellen zu verwenden.

Dann sollten wir fortschrittlichere Algorithmen einsetzen, um zu verhindern, dass Betrüger die Scores leicht manipulieren können. Zum Beispiel sollten wir die Anzahl einzigartiger Konten zählen, die mit einem Contract transagiert haben. Wir könnten auch eine Analyse der Konten durchführen, die in der Vergangenheit damit interagiert haben, um sicherzustellen, dass sie nicht alle aus einer einzigen Quelle stammen. Der Nachteil ist, dass all diese Analysen schwieriger mit mehreren Wahrheitsquellen durchzuführen sind.

Es gibt auch interessante Forschungsarbeiten zur Betrugserkennung bei Smart Contracts, die integriert werden könnten. Mehr Infos hier.

Insgesamt zeigt die überwältigend positive Resonanz, die ich für diesen Hack erhalten habe, dass Nutzer mehr Informationen einfordern – und ich glaube, dass die leichte Verständlichkeit dabei eine entscheidende Rolle gespielt hat.

Kannst du uns ein wenig über dich erzählen?

Ich bin Software-Ingenieur bei ChainSafe und habe früher bei Parity gearbeitet. Ich liebe es, Produkte mit einem Fokus auf gute UX zu entwickeln. Web3 ist für mich ein großartiges Spielfeld, weil alles so komplex ist – zu versuchen, es für möglichst viele Menschen verständlich zu machen, ist eine großartige Herausforderung. Ich bin seit fast 5 Jahren in diesem Bereich tätig, und obwohl ich viele Hackathons besucht habe, bin ich in der Regel Freiwilliger, Mentor oder Juror und kein Teilnehmer. Der Hauptgrund ist, dass ich ein Perfektionist bin und schnelle und unsaubere Lösungen generell nicht mag :).

Wann bist du zum ersten Mal mit MetaMask Snaps in Berührung gekommen und wie war deine Erfahrung?

Interessanterweise haben meine Kollegen bei ChainSafe einen der ersten Snaps überhaupt gebaut – den für Filecoin. Ich habe mir den Code damals wahrscheinlich angesehen, bin aber nicht tiefer eingetaucht.

Zum Zeitpunkt des Hackathons war die Insights-API für Entwickler noch gar nicht verfügbar. Ich sprach mit dem MetaMask-Team in Lissabon und hatte nicht erwartet, eine Benutzeroberfläche zu MetaMask hinzufügen zu können. Sie sagten mir, dass sie kurz vor der Veröffentlichung stehe und ich schon jetzt darauf aufbauen könnte. Tatsächlich war das nur mit einem Custom Build möglich, und die Dokumentation war noch nicht veröffentlicht.

Was unterscheidet MetaMask Snaps von anderen Wallets?

Die Möglichkeit, benutzerdefinierten Code in einem Tab hinzuzufügen und dabei sicherzustellen, dass dieser Code sicher ausgeführt werden kann, öffnet die Tür zu einer riesigen Bandbreite an Erweiterungen. Ich bin sehr gespannt, was daraus entstehen wird.

Erzähl uns, wie es für dich ist, Snaps mit MetaMask zu entwickeln?

Das Template-Monorepo hat den Einstieg zum Kinderspiel gemacht. Die Tatsache, dass ich meinen gesamten Code in einem einzigen Repository schreiben konnte, mit einem einzigen Befehl zum Starten sowohl der Test-Dapp als auch des Snaps – beides mit Auto-Refresh – war eine großartige Entwicklererfahrung.

Was bedeuten Snaps für dich?

Es ist die Erweiterung einer Erweiterung. Kein Produkt kann alle Nutzer zufriedenstellen. Diese kompositionierbare Schicht hinzuzufügen ist eine großartige Möglichkeit für jeden, der sich ein bestimmtes Feature wünscht, es selbst zu entwickeln.

Welche Chancen siehst du in MetaMask Snaps und den Möglichkeiten, die es für den Web3-Bereich eröffnet?

Ich spreche insbesondere über die Insights, die eine unendliche Anpassbarkeit je nach Bedarf ermöglichen. Ich bin überzeugt, dass in Zukunft viele weitere sicherheitsbezogene Insights entwickelt werden.

Hast du einen Rat für Entwickler, die MetaMask Snaps ausprobieren möchten?

Klone das Monorepo und genieße einen sehr schnellen Einstieg.

Mit MetaMask Snaps entwickeln

So legst du mit MetaMask Snaps los:

  1. Schau dir die Entwicklerdokumentation an

  2. Installiere MetaMask Flask

  3. Sieh dir einen MetaMask Snaps-Leitfaden an

  4. Bleib mit uns in Kontakt auf Twitter, in den GitHub-Diskussionen und auf Discord

Halte bei unserem Team Ausschau beim nächsten Hackathon in deiner Nähe! Happy BUIDLing ⚒️

Haftungsausschluss: MetaMask Snaps werden in der Regel von Dritten entwickelt, die nicht mit Consensys Software verbunden sind. Die Nutzung von MetaMask Snaps, die von Dritten entwickelt wurden, erfolgt nach eigenem Ermessen und auf eigenes Risiko, und du stimmst zu, dass du allein für etwaige Verluste oder Schäden verantwortlich bist, die aus solchen Aktivitäten entstehen. Consensys gibt keine ausdrücklichen oder stillschweigenden Garantien, weder mündlich noch schriftlich, in Bezug auf von Dritten entwickelte MetaMask Snaps und lehnt jede Haftung für von Dritten entwickelte Snaps ab. Die Nutzung von Blockchain-bezogener Software ist mit Risiken verbunden, die du bei der Verwendung von MetaMask Snaps vollständig selbst trägst.

KI-übersetzt. Kann Fehler enthalten. Bitte überprüfen Sie die Informationen stets.

Bewerten Sie die Übersetzung
  • MetaMask
    MetaMask

    MetaMask is the world's leading self-custodial crypto wallet and gateway to decentralized finance, built by Consensys.

    Alle Artikel lesen