Trust Score Snap: Simplificando transações usando cores de código

Vencedor do ETHLisbon Hackathon

8 min de leitura
Trust Score Snap: Simplificando transações usando cores de código

MetaMask Snaps é o roteiro para tornar a MetaMask a carteira mais extensível do mundo. Como desenvolvedor, você pode trazer seus recursos e APIs para a MetaMask de formas totalmente novas. Os desenvolvedores Web3 são o núcleo desse crescimento, e esta série tem como objetivo apresentar os novos MetaMask Snaps sendo criados hoje.

Trust Score Snap

Repositório do Snap: https://github.com/Tbaut/template-snap-monorepo

Por que você o criou?

Quando se trata de assinatura de transações no Ethereum, o elefante na sala é que a maioria dos usuários tem muito pouca ideia do que está assinando. Decodificar métodos e argumentos é um bom primeiro passo, mas se os usuários interagirem com um contrato malicioso, as informações visíveis podem ser enganosas. Para contrabalançar isso, pensei em exibir dados quantitativos de forma muito simples, usando cores de código 🟥 🟧 🟩. A ideia é mostrar uma pontuação de confiança com base em dados fáceis de verificar a partir de múltiplas fontes. Escolhi começar com 4 critérios:

  • Quantos usuários interagiram com o smart contract no total.

  • Com que frequência a conta atual interagiu com esse contrato.

  • Qual é a idade desse contrato.

  • Se o código desse contrato foi verificado.

Você pode nos guiar pela implementação técnica?

A função principal de insights

O snap é muito simples e fácil de estender. Aqui está o código completo que vamos analisar.

Quando a aba de insights é clicada na MetaMask, a função onTransaction é chamada. Dentro dela, chamamos cada função que nos fornece os critérios que decidimos levar em conta.

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

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

Essas funções geralmente chamam uma API e processam os resultados. Vamos nos aprofundar em uma delas para entender melhor.

Determinar uma pontuação de confiança com base nas interações gerais

Vamos nos aprofundar na função que atribui uma pontuação com base no número total de transações que um contrato recebeu. Usamos a API do Etherscan aqui, mas qualquer outra API poderia funcionar para verificar os mesmos dados.

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

Nem todas as pontuações são iguais

Agora que temos um TrustResult para cada um dos nossos critérios, é hora de aplicar pesos. De fato, nem todos os critérios de pontuação de confiança devem ter o mesmo peso. Por exemplo, a quantidade de transações anteriores com o contrato tem um custo. Se um golpista quisesse manipulá-la, precisaria gastar ETH em gas. Por isso, esse critério é considerado mais difícil de manipular e, portanto, mais importante — atribuí a ele um peso de 3.

Da mesma forma, a idade do contrato não pode ser contornada por um atacante: ele precisaria implantá-lo e depois aguardar antes de lançar seu ataque, caso quisesse obter uma pontuação de confiança alta. Atribuí a ele um peso de 2.

Os demais critérios são considerados mais fracos e têm peso 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);
};
Copiar

Apresentar a pontuação final

Por fim, agora que temos a pontuação de confiança de um smart contract, precisamos exibi-la de forma simples. A API de insights da MetaMask permite apenas exibir pares de chave e valor. As chaves aparecem em negrito, e os valores têm peso de fonte normal. Percebi que, usando emojis, poderia criar uma interface que não intimida os usuários, ao mesmo tempo em que exibe todas as informações coletadas.

A função que transforma a pontuação de confiança em emojis:

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

E a parte de retorno da função onTransaction, com alguns ajustes para exibir os pares de chave e valor de forma elegante:

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

Por fim, criei uma interface muito simples para chamar 2 tipos de contratos: um contrato Uniswap muito conhecido e amplamente utilizado, e um contrato de armazenamento implantado recentemente — o apresentado por padrão no Remix. Se você usasse este snap e interagisse com o contrato do roteador Uniswap, veria o seguinte:

Quais são os próximos passos se você fosse implementar isso?

Isso é apenas a ponta do iceberg do que poderia dar mais confiança aos usuários ou evitar que sejam vítimas de phishing. O primeiro passo óbvio seria usar mais fontes para os nossos dados. A verificação do contrato já utiliza Sourcify e Etherscan, mas seria melhor usar múltiplas fontes para cada critério.

Em seguida, deveríamos aplicar algoritmos mais avançados para evitar que golpistas consigam manipular as pontuações com facilidade. Por exemplo, deveríamos contar a quantidade de contas únicas que realizaram transações com um contrato. Também poderíamos fazer uma análise das contas que interagiram com ele no passado, para garantir que não se originam todas de uma única fonte. A desvantagem é que toda essa análise é mais difícil de realizar usando múltiplas fontes de verdade.

Há também pesquisas interessantes sobre detecção de golpes em smart contracts que poderiam ser integradas. Mais informações aqui.

No geral, a enorme quantidade de reações positivas que recebi por esse hack mostra que os usuários estão pedindo mais informações, e acredito que o fato de ser fácil de entender desempenhou um papel fundamental nisso.

Você pode nos contar um pouco sobre você?

Sou engenheiro de software na ChainSafe e trabalhei na Parity no passado. Adoro criar produtos com foco em uma boa experiência do usuário. Web3 é um ótimo campo de experimentação para mim, porque tudo é muito complexo — tentar torná-lo compreensível para o maior número possível de pessoas é um grande desafio. Estou no espaço há quase 5 anos e, embora tenha participado de muitos hackathons, geralmente sou voluntário, mentor ou juiz, em vez de participante. O principal motivo é que sou perfeccionista e geralmente não gosto de soluções rápidas e improvisadas :).

Quando você foi apresentado ao MetaMask Snaps pela primeira vez e como foi essa experiência?

Curiosamente, meus colegas na ChainSafe criaram um dos primeiros snaps já desenvolvidos, o do Filecoin. Provavelmente dei uma olhada no código na época, mas não me aprofundei.

No momento do hackathon, a API de insights ainda não estava disponível para os desenvolvedores. Eu estava conversando com a equipe da MetaMask em Lisboa e não esperava conseguir adicionar uma interface de usuário à MetaMask. Eles me disseram que estava prestes a ser lançada e que eu poderia começar a desenvolver com ela agora. Na prática, isso só estava disponível com uma build personalizada, e a documentação ainda não havia sido publicada.

O que diferencia o MetaMask Snaps de outras carteiras?

Ter a capacidade de adicionar código personalizado em uma aba, garantindo ao mesmo tempo que esse código é seguro para execução, abre as portas para uma enorme variedade de melhorias. Estou muito animado para ver o que vai surgir disso.

Como é para você criar Snaps com a MetaMask?

O monorepo de template tornou o início muito fácil. O fato de todo o meu código poder ser escrito em um único repositório, com um único comando para iniciar tanto o dapp de teste quanto o snap — ambos com atualização automática — foi uma ótima experiência para o desenvolvedor.

O que os Snaps significam para você?

É a extensão de uma extensão. Nenhum produto consegue atender a todos os usuários. Adicionar essa camada combinável é uma grande oportunidade para qualquer pessoa que queira um recurso específico e prefira desenvolvê-lo por conta própria.

Que oportunidades você enxerga no MetaMask Snaps e nas possibilidades que ele abre para o espaço Web3?

Vou falar especificamente sobre os insights, que estão desbloqueando uma personalização infinita de acordo com as necessidades. Aposto que muitos mais insights relacionados à segurança serão desenvolvidos no futuro.

Algum conselho que você gostaria de compartilhar com desenvolvedores interessados em experimentar o MetaMask Snaps?

Clone o monorepo e aproveite um início muito rápido.

Desenvolvendo com MetaMask Snaps

Para começar com o MetaMask Snaps:

  1. Confira a documentação para desenvolvedores

  2. Instale o MetaMask Flask

  3. Confira um guia do MetaMask Snaps

  4. Fique conectado conosco no Twitter, nas discussões do GitHub e no Discord

Fique de olho na nossa equipe no próximo hackathon perto de você! Bom BUIDLing ⚒️

Aviso legal: Os MetaMask Snaps são geralmente desenvolvidos por terceiros que não a Consensys Software. O uso de MetaMask Snaps desenvolvidos por terceiros é feito a seu próprio critério e risco, com o entendimento de que você será o único responsável por qualquer perda ou dano resultante de tais atividades. A Consensys não oferece nenhuma garantia expressa ou implícita, seja verbal ou escrita, em relação a MetaMask Snaps desenvolvidos por terceiros, e se isenta de toda responsabilidade por Snaps desenvolvidos por terceiros. O uso de softwares relacionados a blockchain envolve riscos, e você os assume integralmente ao utilizar o MetaMask Snaps.

Traduzido por IA. Pode conter erros. Por favor, verifique sempre as informações.

Avalie a tradução
  • MetaMask
    MetaMask

    A principal carteira cripto de autocustódia e portal para a Web3, desenvolvida pela Consensys.

    Ler todos os artigos