如何高效地为智能合约审计做好准备

  • zealynx
  • 发布于 2024-02-21 21:44
  • 阅读 11

本文主要介绍了在将智能合约项目提交给安全审计之前,如何进行充分的准备工作。内容涵盖了项目准备的重要性,包括清晰地阐述协议概念、工作流程,提供合约概述,明确不变量,以及使用完善的库。此外,文章还强调了开发过程中的良好实践,如遵循Solidity的最佳实践、进行充分的测试和内部安全审查,并提供了关于安全性考虑和定义安全审查范围的建议。

你和你的团队最终决定将你的项目和智能合约送去进行安全审查。你们中的一些人甚至可能不得不努力说服公司的决策者,让他们相信这是必要的。

现在,你不仅要选择一家拥有值得信赖的专业人士的公司(就像我们在Zealynx一样),而且还要确保你的智能合约为安全审查做好尽可能充分的准备。

让你的项目准备就绪意味着什么,为什么这很重要?

你是否意识到你花了多少时间来计划、讨论、实施和微调项目的功能?嗯,审查你的代码的安全审查员可没有。

你的开发者可能已经与产品团队进行过一些会面,加上在实施代码时进行了更多时间的讨论。因此,你现在的目标是将你的项目传递给审计公司,以便他们能够用尽可能少的时间来理解代码的预期结果,并拥有最干净、最具可读性的代码。

协议概念和工作流程

安全审查员需要了解的最初信息之一是协议的类型、目标和功能。

根据我们分析DeFi协议和参与公开竞赛的经验,我们遇到了一些用于展示已实施的关键功能的有趣方法。

一种方法,通常在较大的协议中观察到,包括一个专门的部分来解释概念、特性或功能。

无标题图片

无标题图片

第二种方法,通常用于较小的协议或范围较窄的安全审查,是为其主要功能提供预期的工作流程。

我们最近在参与CodeHawks的第一次竞赛时遇到了这种方法。

无标题图片

合约概述

在合约概述中,你可以灵活地提供你认为必要的尽可能多的信息。当然,你提供的信息越多,安全审查员在过程中进行研究和数据收集所需的时间就越少。

这个概念是包括范围内的智能合约的名称,并提及和/或解释它们在协议的主要功能中的作用。此外,提供合约本身中一些关键功能的解释也是有益的。

UniswapAave这样的主要协议在其文档中提供了这样的合约概述。

如果你想提升你的方法,可以考虑聘请一位技术作家,或者从你的团队中找一位有较强写作能力的人,来创建一个全面的智能合约分解,这些智能合约在安全审查的范围内。

Zealynx团队成员撰写的关于GravitaSpiral DAO的两篇文章就是很好的例子。

识别不变量

不变量是在一组明确定义的假设下必须始终为真的条件。

例如:

  • 除非调用mint或burn,否则ERC20Token的总供应量不会改变。
  • 合约中所有余额的总和应等于总供应量。
  • 每个钱包最多可以有100张票
  • 铸造门票的窗口期为72小时

提供此信息具有巨大的价值。当你提供这些数据时,你正在向安全审查员提供必须无一例外地保持为真的高度具体的要求。

此信息有助于测试,并有助于使用安全审查员可用的工具来尝试发现代码中的漏洞,例如模糊测试和形式验证工具。

使用的库

将现有的、完善的、经过充分测试的库集成到你的智能合约中有许多原因。但是,我们现在不会深入研究这些细节。

指定你的合约使用的库的一个好地方是在前面提到的合约概述中。

这种做法有助于理解代码以及合约本身中使用的引用,从而有助于熟悉代码库。

NatSpec & 注释

总的来说,开发者应该努力编写简洁的代码,并为合约、函数、变量等使用全面的命名约定。但是,在代码中提供额外的细节可以大大方便安全审查员的工作。

需要记住两件事:

  • NatSpec。当我们遇到一个智能合约,在其合约和函数之上有一个详细的NatSpec时,作为安全审查员,它使我们更容易理解我们应该在代码本身中找到什么。
  • 内联注释。如果你在Yul中有一段代码,或者你认为可能很复杂的任何逻辑,添加内嵌注释来解释这段代码旨在实现什么,将有助于安全审查员验证它。

开发和良好实践

常见的Solidity最佳实践

与任何编程语言一样,Solidity也有自己的一套最佳实践,可以在合约审查期间极大地帮助安全审查员。

我们想强调一些关键的实践,并提供一个经常报告的非关键问题的列表。这些可以显著提高你的代码质量,并释放安全审查员的时间,让他们专注于代码中更相关的部分。

首先,在你的合约中保持一个定义良好的结构至关重要。一切都应该在合约中各有其位。

Solidity文档提供了一个全面的代码布局部分,其中包含深入的细节,强烈建议阅读它以熟悉推荐的结构。

在代码布局部分中,我们想强调并扩展推荐的用于排列合约中所有元素的顺序:

1Pragma statements
2Import statements
3Interfaces
4Libraries
5Contracts
6State variables
7Events
8Function Modifiers
9Struct, Arrays or Enums
10Constructor
11Fallback — Receive function
12External visible functions
13Public visible functions
14Internal visible functions
15Private visible functions

理解并遵守这种结构的一个极好的补充是在代码中“声明”它,方法是在引入一个新的元素部分之前添加一个注释作为标题。

1// EXTERNAL FUNCTIONS
2[...]
3// PUBLIC FUNCTIONS
4[...]
5// INTERNAL FUNCTIONS
6[...]

通常,我们在公开竞赛中会遇到大量的非关键或信息性问题列表,其中很大一部分往往是重复的。

因此,这里列出了一些你应确保在将合约提交进行安全审查之前解决的问题:

  • 未被合约调用的公共函数应声明为external
  • 应定义常量,而不是使用魔法数字
  • 应使用自定义错误,而不是revert()/require()
  • 地址不应该硬编码
  • 变量不需要初始化为零
  • 非外部/公共函数名称应以下划线开头
  • 私有/内部状态变量的名称应以一个下划线为前缀
  • 避免使用浮动pragma
  • 考虑将msg.sender检查移动到修饰符中
  • 建议使用命名映射

测试

多加测试,就像没有明天一样——就像你的生命(或金钱)依赖于它一样。

通常,当测试开发者没有测试过的部分代码时,会出现问题。这就是为什么测试你添加的每个函数至关重要。

审计公司可能会进行其他类型的测试,例如模糊测试、不变量测试和形式验证。然而,了解它们的存在是有益的。

内部安全审查

在将你的项目发送进行安全审查之前,必须了解一件事:无论你将它发送给单独的审计师还是审计公司,都不能保证你的代码完全没有错误。

在理想的情况下,审查合约的人越多,尤其是在不同的阶段,代码越安全的可能性就越大。

这就是我们想强调单独的审计师或小型审计公司(通常由2-4名安全审查员组成)的价值的地方。

无论是作为你团队的一员还是作为承包商雇佣,让具有Web3安全知识的人员在安全审查过程的初始阶段审查代码至关重要。

这样一个人或团队可能能够在早期阶段识别出关键问题。因此,请考虑将此步骤纳入你的流程。

Solidity 模式

Solidity编程语言仍处于早期阶段。然而,已经确定了一些推荐的模式,用于开发你的智能合约时应用。

让我们重点介绍其中的一些模式,但请务必从源头熟悉它们。

  • 从合约中提款。在效果之后发送资金的推荐方法是使用提款模式。
  • 限制访问。你永远无法阻止任何人或计算机读取你的交易或合约状态的内容,但你可以通过使用加密使其变得更加困难。
  • 状态机。合约通常充当状态机,这意味着它们具有某些阶段,在这些阶段中它们的行为不同,或者可以调用不同的函数。
  • 检查效果交互。减少恶意合约在外部调用后试图劫持控制流的攻击面,并避免重入攻击。
  • 代理委派。引入在不破坏任何依赖关系的情况下升级智能合约的可能性。
  • 永久存储。因为旧合约实际上没有更新到新版本,累积的存储仍然位于旧地址。

安全注意事项

作为一名开发者,至关重要的是,你能够实现代码,同时了解经常引入的潜在安全问题,从而使你能够避免这些问题。

如前所述,我们正在收集一些问题,使你能够更深入地研究提供的来源。

安全审查范围

现在你已经准备好了你的代码并遵循了以上所有的建议,现在是开始准备安全审查本身的文档的时候了。

首先,确保你告知单独的审计师或团队,你希望他们专注于审查和错误报告的项目中的哪些智能合约。

但是,这并不意味着这些是你应该与他们共享的唯一文件。理想情况下,你应该提供所有相关和必要的文件,甚至整个项目,以便为安全审查员提供尽可能多的上下文。

已知问题

你可能在你自己的内部安全审查或之前的审计中发现了某些问题。

在这种情况下,在提供的文档中列出这些问题可以节省时间。这确保了安全审查员知道这些问题,并且不需要花时间搜索和报告它们。

顾虑

在Web3开发领域和区块链中,事情在不断发展。这意味着你可能在你的知识中存在一些空白,以及顾虑、问题或恐惧,特别是如果由于你已实现的功能而有大量的资金处于风险之中。

与安全审查员分享这些顾虑会非常有益。安全审查员努力像黑客一样思考,因此你的见解可以引导他们朝着正确的方向前进,因为他们试图识别漏洞。

入门

自述文件

这可能看起来很明显,但请务必在你的框架中包含一个Readme.md文件。此文件应包含基本信息以及确保你的项目可以在另一台机器上编译和运行所需的任何强制性要求。

要求

  • 你的项目中是否集成了任何依赖项?
  • 你是否正在使用特定的测试框架?
  • 使用特定版本的任何工具是否有特定原因?

请记录并分享此信息。

快速开始

你已经在自己的机器上工作了一段时间,因此你可能遇到了各种编译器问题,安装了依赖项或工具。 在提交项目进行安全审查之前,请确保你可以在另一台机器上成功编译和运行它。保存用于此目的的命令,以便你可以在Readme.md文件的“入门”部分中共享它们。

审计联系方式 👥

📲 Telegram

📧 联系方式

  • 原文链接: zealynx.io/blogs/How-to-...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
zealynx
zealynx
江湖只有他的大名,没有他的介绍。