信任评分 Snap:用代码颜色简化交易

ETHLisbon 黑客马拉松获奖者

8 分钟阅读
信任评分 Snap:用代码颜色简化交易

MetaMask Snaps 是让 MetaMask 成为全球最具扩展性钱包的发展路线图。作为开发者,您可以通过全新的方式将您的功能和 API 带入 MetaMask。Web3 开发者是这一增长的核心,本系列旨在展示当今正在构建的创新 MetaMask Snaps。

信任评分 Snap

Snap 代码库: https://github.com/Tbaut/template-snap-monorepo

您为什么要构建它?

在以太坊上进行交易签名时,一个不容忽视的问题是:大多数用户对自己正在签署的内容几乎一无所知。解码方法和参数是一个良好的第一步,但如果用户与恶意合约交互,可见信息可能会产生误导。为了应对这一问题,我想到了以非常简单的方式展示量化数据,并使用颜色代码 🟥 🟧 🟩。其核心思路是基于可从多个来源轻松验证的数据,展示一个信任评分。我选择从以下 4 个维度入手:

  • 与该智能合约交互过的用户总数。

  • 当前账户与该合约的交互频率。

  • 该合约的部署时长。

  • 该合约代码是否已通过验证。

能否带我们了解一下技术实现过程?

insights 主函数

这个 Snap 非常简洁,且易于扩展。以下是我们将要介绍的完整代码

当 MetaMask 中的 insights 标签被点击时,onTransaction 函数将被调用。在该函数内部,我们调用各个函数,分别获取我们决定纳入考量的各项维度数据。

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

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

这些函数通常会调用某个 API,并对结果进行处理。让我们深入了解其中一个函数。

基于整体交互情况确定信任评分

让我们深入了解一个函数,该函数根据合约收到的交易总量来给出评分。我们在这里使用了 Etherscan API,但任何其他 API 都可以用来验证相同的数据。

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

评分权重各有不同

现在我们已经为每个维度获得了 TrustResult,接下来需要应用权重。事实上,并非所有维度的信任评分都应具有相同的权重。例如,与合约过往交易数量这一维度是有成本的——如果有人想要刷高这个分数,需要支付一定的 ETH 作为 Gas 费。因此,这个维度被认为更难被操控,也更为重要,我给它赋予了权重 3。

同样,合约的部署时长也无法被攻击者轻易规避——他们必须先部署合约,然后等待一段时间才能发动攻击,以获得较高的信任评分。我给它赋予了权重 2。

其他维度被认为相对较弱,权重均为 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);
};
复制

展示最终评分

最终,我们得到了智能合约的信任评分,需要以简洁的方式将其呈现出来。MetaMask insights API 仅支持展示键值对,其中键以粗体显示,值以常规字重显示。我想到通过使用 emoji,可以创建一个对用户友好、不会造成压迫感的界面,同时仍能展示所有收集到的信息。

将信任评分转换为 emoji 的函数:

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

以及 onTransaction 函数的返回部分,通过一些技巧以美观的方式展示键值对:

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

最后,我创建了一个非常简单的界面,用于调用两种类型的合约:一个是广为人知且被广泛使用的 Uniswap 合约,另一个是最近刚部署的存储合约(即 Remix 默认展示的合约)。如果您使用此 Snap 并与 Uniswap 路由合约交互,您将看到以下内容:

如果您要继续实现这个项目,下一步计划是什么?

这仅仅是能够给予用户信心、或防止用户遭受钓鱼攻击的信息的冰山一角。最显而易见的第一步是为我们的数据引入更多来源。合约验证目前已使用 Sourcify 和 Etherscan,但最好能为每个维度都使用多个数据来源。

其次,我们应该应用更先进的算法,以防止攻击者轻易操控评分。例如,我们应该统计与合约交互过的唯一账户数量。我们还可以对过去与合约交互的账户进行分析,以确保它们并非全部来自同一来源。不足之处在于,在使用多个真实数据来源的情况下,这些分析会更难以实现。

此外,目前也有一些关于智能合约欺诈检测的有趣研究成果可供参考和整合。更多信息请点击此处

总体而言,我在这次黑客松中收到的大量积极反馈表明,用户迫切需要获取更多信息,而我认为内容易于理解这一点也发挥了关键作用。

能否简单介绍一下您自己?

我是 ChainSafe 的一名软件工程师,曾在 Parity 工作过。我热衷于构建注重良好用户体验的产品。Web3 对我来说是一个绝佳的试验场,因为这里的一切都如此复杂,努力让尽可能多的人能够理解它,是一项极具挑战性的事业。我进入这个领域已将近 5 年,虽然参加过许多黑客松,但通常是以志愿者、导师或评委的身份参与,而非作为参赛选手。主要原因是我是一个完美主义者,通常不喜欢快速而粗糙的解决方案 :)。

您是什么时候第一次接触 MetaMask Snaps 的?当时的体验如何?

有趣的是,我在 ChainSafe 的同事构建了有史以来最早的 Snap 之一——用于 Filecoin 的 Snap。我当时可能看过那段代码,但没有深入研究。

在参加黑客松时,insights API 实际上还没有向开发者开放。我当时在里斯本与 MetaMask 团队交流,完全没想到能够为 MetaMask 添加用户界面。他们告诉我该功能即将发布,我现在就可以基于它进行开发。事实上,这只能通过自定义构建版本来实现,相关文档也尚未发布。

MetaMask Snaps 与其他钱包有何不同?

能够在标签页中添加自定义代码,同时确保该代码可以安全执行,这为大量功能增强打开了大门。我非常期待未来由此诞生的各种可能性。

请谈谈您使用 MetaMask 构建 Snaps 的体验?

模板 monorepo 让上手变得轻而易举。所有代码都可以在同一个代码库中编写,只需一条命令即可同时启动测试 dapp 和 Snap,并且两者都支持自动刷新,这带来了极佳的开发体验。

Snaps 对您意味着什么?

它是扩展之上的扩展。没有任何产品能够满足所有用户的需求。添加这一可组合层,为任何有功能需求的人提供了自行构建的绝佳机会。

您认为 MetaMask Snaps 为 Web3 领域带来了哪些机遇和可能性?

我想特别谈谈 insights 功能,它根据不同需求解锁了无限的自定义可能性。我相信未来将会有更多与安全相关的 insights 被开发出来。

对于有意尝试 MetaMask Snaps 的开发者,您有什么建议?

克隆 monorepo,享受极速上手的体验。

使用 MetaMask Snaps 进行构建

开始使用 MetaMask Snaps:

  1. 查阅开发者文档

  2. 安装 MetaMask Flask

  3. 参考 MetaMask Snaps 指南

  4. 通过 TwitterGitHub 讨论区Discord 与我们保持联系

请关注我们团队在您附近举办的下一场黑客松!祝 BUIDL 愉快 ⚒️

免责声明:MetaMask Snaps 通常由 Consensys Software 以外的第三方开发。使用第三方开发的 MetaMask Snaps 须由您自行决定并承担相应风险,且您同意对因此类活动导致的任何损失或损害承担全部责任。Consensys 对第三方开发的 MetaMask Snaps 不作任何明示或暗示的保证,并对第三方开发的 Snaps 免除一切责任。使用区块链相关软件存在风险,使用 MetaMask Snaps 即表示您完全接受并承担这些风险。

AI 翻译。可能包含错误。请务必核实信息。

评价此翻译
  • MetaMask
    MetaMask

    由 Consensys 打造的领先自托管加密钱包和 Web3 入口。

    阅读所有文章