智能合约开发的最佳实践 – 强烈推荐

译者注:这是距今为止行业内最全面的智能合约开发指南,强烈推荐。

> * 来源:https://yos.io/2019/11/10/smart-contract-development-best-practices/ 作者:[Yos Riady](https://yos.io/about/) > * 译文出自:[登链翻译计划](https://github.com/lbc-team/Pioneer) > * 译者:[Tiny 熊](https://learnblockchain.cn/people/15) > * 本文永久链接:[learnblockchain.cn/article…](https://learnblockchain.cn/article/1) ![](https://img.learnblockchain.cn/2020/09/15/16001337715241.jpg) 软件开发的历史已有数十年之久。我们受益于半个世纪以来积累的最佳实践,设计模式和智慧。 相反,智能合约开发才刚刚开始。2015推出的以太坊和 Solidity 仅有几年的时间。 加密空间是一个不断发展的未知领域。**没有确定的工具堆栈**来构建去中心化应用。对于智能合约,没有诸如[设计模式](https://en.wikipedia.org/wiki/Design_Patterns)或[代码整洁之道](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882)之类的开发人员手册。有关工具和最佳实践的信息遍布各处。 你正在阅读**我这份希望它已经存在的指南**。总结了我从以太坊生态系统中编写智能合约,构建去中心化应用程序和开源项目中学到的经验教训。 >这本手册是线上的文件。如果你有任何反馈或建议,请随时发表评论或[直接给我发送电子邮件](mailto:hello@yos.io)。 ## 这是给谁的 本手册适用于: * 刚开始使用智能合约的开发人员,以及 * 经验丰富的Solidity开发人员希望将他们的工作提升到一个新的水平。 但是,这并不意味着要介绍[Solidity](https://learnblockchain.cn/docs/solidity/)语言。 那就直接开始正文吧,以下我的一些建议: ## 使用开发环境 使用[Truffle](https://learnblockchain.cn/docs/truffle/)之类的开发环境(或者,[Embark](https://learnblockchain.cn/article/566), [Builder](https://buidler.dev/) [dapp.tools](http://dapp.tools/))等开发环境可以快速高效地工作。 ![](https://img.learnblockchain.cn/2020/09/15/16001341569297.jpg) 使用开发环境可以加快经常重复执行的任务,例如: * 编译合约 * 部署合约 * 调试合约 * 升级合约 * 运行单元测试 ![](https://img.learnblockchain.cn/2020/09/15/16001343301985.jpg) 例如,Truffle 提供以下有用的命令: * **compile:**将Solidity合约编译为其ABI和字节码格式。 * **console**:实例化一个交互式JS控制台,你可以在其中调用web3合约并与之交互。 * **test**:运行合约的单元测试套件。 * **migrate**:将你的合约部署到网络。 Truffle支持提供其他功能的插件。例如,[`truffle-security`](https://github.com/ConsenSys/truffle-security)提供智能合约安全性验证。 [`truffle-plugin-verify`](https://learnblockchain.cn/article/1314)在区块链浏览器上发布你的合约。你还可以创建[自定义插件](https://www.trufflesuite.com/docs/truffle/getting-started/writing-external-scripts#creating-a-custom-command-plugin)。 同样,[Builder](https://hardhat.org/plugins/) 也有越来越多的插件支持给以太坊智能合约开发人员使用。 无论使用哪种开发环境,选择一套好的工具都是必须。 ## 本地开发 使用[Ganache](https://www.trufflesuite.com/ganache)(或[Ganache CLI](https://github.com/trufflesuite/ganache-cli))运行本地区块链进行开发,以“加快迭代周期”。 ![](https://img.learnblockchain.cn/2020/09/15/16001346187508.jpg) 在主网上,以太坊交易[得付费](https://www.investopedia.com/terms/g/gas-ethereum.asp),可能需要[数分钟](https://ethgasstation.info/)才确认。使用本地链跳过所有这些等待。在本地运行合约交易免费且即时。 ![](https://img.learnblockchain.cn/2020/09/15/16001346606172.jpg) Ganache带有一个内置的区块浏览器,可显示你解码后的交易、合约和事件。且本地环境是[可配置](https://www.trufflesuite.com/docs/ganache/reference/ganache-settings),以满足你的测试需求。 且设置简便快捷。 [在这里下载](https://www.trufflesuite.com/ganache). ## 使用静态分析工具 静态分析或“linting”通过运行程序分析代码中的编程错误。在智能合约开发中,这对于捕获编译器可能错过的“代码风格不一致”和“易受攻击的代码”很有用。 ### 1. Linters ![](https://img.learnblockchain.cn/2020/09/15/16001347755489.jpg) 使用[solhint](https://github.com/protofire/solhint)和[Ethlint](https://github.com/duaraghav8/Ethlint) 分析代码,Solidity的Linter与其他语言(例如JSLint)的linter相似。它们提供安全性和代码风格指南验证。 ### 2.安全性分析 ![](https://img.learnblockchain.cn/2020/09/15/16001352402449.jpg) 安全分析工具识别[智能合约漏洞](https://yos.io/2018/10/20/smart-contract-vulnerabilities-and-how-to-mitigate-them/),这些工具运行一组漏洞检测器,并打印出发现的所有问题的摘要。开发人员可以在整个实现阶段使用此信息来查找和解决漏洞。 可以选择:[Mythril](https://github.com/ConsenSys/mythril)·[Slither](https://github.com/crytic/slither)·[Manticore](https://github.com/trailofbits/manticore)·[MythX](https://mythx.io/)·[Echidna](https://github.com/crytic/echidna)·[Oyente](https://github.com/melonproject/oyente) ### 额外:使用Pre-Commit Hook 通过使用[`husky`](https://github.com/typicode/husky)设置[Git Hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks),使你的开发人员体验变得无缝,Pre-Commit Hook可让你在每次提交之前运行linters。例如: ``` // package.json { "scripts": { "lint": "./node_modules/.bin/solhint -f table contracts/**/*.sol", }, "husky": { "hooks": { "pre-commit": "npm run lint" } }, } ``` 上面的代码片段在每次提交之前运行一个预定义的`lint` 任务,如果代码中存在突出的样式或安全性违规,则会失败。此设置使你团队中的开发人员能够在迭代中与linter一起使用。 ## 了解安全漏洞 编写没有错误的软件非常困难。防御性编程技术只能走这么远。幸运的是,你可以通过部署新代码来修复错误。传统软件开发中的补丁程序频繁且直接。 ![](https://img.learnblockchain.cn/2020/09/15/16001353110014.jpg) 但是,智能合约是“不可变更的”。有时无法[升级](https://yos.io/2018/10/28/upgrading-solidity-smart-contracts/)已生效的合约。在这方面,智能合约比软件开发更接近于虚拟硬件开发。 更糟糕的是,合约错误会导致巨大的财务损失。 [DAO Hack](https://medium.com/swlh/the-story-of-the-dao-its-history-and-consequences-71e6a8a551ee)损失了超过1150万以太币(在被黑客入侵时为7000万美元,现在超过了20亿美元),第二名[Parity Hack](https://hackernoon.com/parity-wallet-hack-2-electric-boogaloo-e493f2365303)损失了2亿美元的用户资金,现在DeFi领域[$ 百亿](https://defipulse.com/)市场规模一旦出错,损失将非常惨重。 智能合约开发需要与Web开发完全不同的心态。 “快速行动并打破常规”在这里不适用。你需要预先投入大量资源来编写无错误的软件。作为开发人员,你必须: 1. 熟悉Solidity [安全性](https://yos.io/2019/11/10/smart-contract-development-best-practices/) [漏洞](https://yos.io/2018/10/20/smart-contract-vulnerabilities-and-how-to-mitigate-them/),和 2. 扎实理解[设计](https://consensys.github.io/smart-contract-best-practices/recommendations/)和 [模式](https://github.com/fravoll/solidity-patterns),例如:付款提取与推送方式 以及遵循 ”检查“ - "更改" - ”交互“等。 3. 使用防御性编程技术:静态分析和单元测试。 4. 审计你的代码。 以下各节将详细说明要点(3)和(4)。 >**初学者提示:**你可以使用[Ethernauts](https://ethernaut.openzeppelin.com/)以交互方式练习Solidity安全性。 ## 编写单元测试 借助**全面的测试套件**,尽早发现错误和意外行为。不同的场景测试协议可帮助你识别极端情况。 Truffle使用[Mocha](https://mochajs.org/)测试框架和[Chai](https://www.chaijs.com/)进行断言。你可以使用Javascript针对合约的包装器编写单元测试,就像前端[DApp](https://learnblockchain.cn/tags/DApp)如何调用你的合约。 ![](https://img.learnblockchain.cn/2020/09/15/16001353660527.jpg) 从Truffle v5.1.0开始,你可以中断测试以对测试流程进行[debug](https://www.trufflesuite.com/docs/truffle/getting-started/debugging-your-contracts#in-test-debugging)并启动调试器,从而允许你设置断点,检查Solidity变量等。 ![](https://img.learnblockchain.cn/2020/09/15/16001353786145.jpg) Truffle缺少一些对于测试智能合约必不可少的功能。安装[openzeppelin-test-helpers](https://github.com/OpenZeppelin/openzeppelin-test-helpers)可让你访问许多重要的实用工具以验证合约状态,例如**匹配合约事件**和**向前移动时间**。 译者注: 调试智能合约还有一个选择是使用 [Build EVM 及 console.log](https://learnblockchain.cn/article/1371), 它支持在Solidity源码中打印日志查看变量。 >或者,如果你更喜欢使用其他测试运行器,[OpenZeppelin测试环境](https://github.com/OpenZeppelin/openzeppelin-test-environment)提供了与工具无关的选项。 ## 衡量测试覆盖率 编写测试是不够的。你的测试套件必须可靠地捕获回归。**[测试覆盖率](https://en.wikipedia.org/wiki/Code_coverage)**衡量测试的有效性。 ![](https://img.learnblockchain.cn/2020/09/15/16001354069788.jpg) 具有较高测试覆盖率的程序在测试期间将执行更多代码。这意味着与覆盖率较低的代码相比,它更容易发现未被检测到的错误。 你可以使用[`solidity-coverage`](https://github.com/sc-forks/solidity-coverage)收集Solidity代码覆盖率 ### 配置持续集成 拥有测试套件后,请“尽可能频繁地”运行它。有几种方法可以实现此目的: 1. 像我们之前介绍的,设置Git Hook,或者 2. 设置一个CI(持续集成:Continuous integration) 管道,在每次Git推送后执行测试。 如果你要使用现成的CI,请查看[Truffle团队](https://www.trufflesuite.com/teams)或[super blocks](https://superblocks.com/).,它们为连续进行智能合约测试提供了托管环境。 ![](https://img.learnblockchain.cn/2020/09/15/16001354347819.jpg) 托管CI会定期运行你的单元测试,以最大程度地放心。你还可以监视已部署合约的交易,状态和事件。 ## 安全审计合约 安全审计可帮助你“发现”防御性编程技术(linting,单元测试,设计模式)所遗漏的未知问题。 ![](https://img.learnblockchain.cn/2020/09/15/16001354443476.jpg) 在这个探索阶段,你需要尽最大努力破坏合约, 如:提供意外的输入,以不同的角色调用函数等。 没有什么可以取代人工安全审计,尤其是当黑客入侵的是[整个DeFi生态系统](https://medium.com/@peckshield/bzx-hack-full-disclosure-with-detailed-profit-analysis-e6b1fa9b18fc)时。 >️在进行下一阶段之前,你的代码应该已经通过了前面部分提到的静态分析。 ## 聘请外部审计师 聘请(昂贵的)安全审计员来升级以太坊中的主要协议,他们深入研究其代码以发现潜在的安全漏洞。这些审计员结合使用专有和开源静态分析工具,例如: * [Manticore](https://github.com/trailofbits/manticore/releases/tag/0.1.6) - 一个模拟器,能够模拟针对EVM字节码的复杂的多合约和多交易攻击。 * [Ethersplay](https://github.com/crytic/ethersplay) - 一种图形化EVM反汇编程序,能够进行方法还原,动态跳转计算,源代码匹配和二进制比较。 * [Slither](https://github.com/crytic/slither) - 静态分析器,它检测常见错误,例如重入错误,构造函数,方法访问等。 * [Echidna](https://github.com/crytic/echidna) - 面向EVM字节码的下一代智能模糊器。 审计员将帮助**识别协议中任何设计和架构级别的风险**,并知道你关于常见的智能合约漏洞。 ![](https://img.learnblockchain.cn/2020/09/15/16001354660778.jpg) 在该过程的最后,你将获得一份报告,其中总结了审计师的发现...

  • 来源:https://yos.io/2019/11/10/smart-contract-development-best-practices/ 作者:Yos Riady
  • 译文出自:登链翻译计划
  • 译者:Tiny 熊
  • 本文永久链接:learnblockchain.cn/article…

软件开发的历史已有数十年之久。我们受益于半个世纪以来积累的最佳实践,设计模式和智慧。

相反,智能合约开发才刚刚开始。2015推出的以太坊和 Solidity 仅有几年的时间。

加密空间是一个不断发展的未知领域。没有确定的工具堆栈来构建去中心化应用。对于智能合约,没有诸如设计模式或代码整洁之道之类的开发人员手册。有关工具和最佳实践的信息遍布各处。

你正在阅读我这份希望它已经存在的指南。总结了我从以太坊生态系统中编写智能合约,构建去中心化应用程序和开源项目中学到的经验教训。

这本手册是线上的文件。如果你有任何反馈或建议,请随时发表评论或直接给我发送电子邮件。

这是给谁的

本手册适用于:

  • 刚开始使用智能合约的开发人员,以及
  • 经验丰富的Solidity开发人员希望将他们的工作提升到一个新的水平。

但是,这并不意味着要介绍Solidity语言。

那就直接开始正文吧,以下我的一些建议:

使用开发环境

使用Truffle之类的开发环境(或者,Embark, Builder dapp.tools)等开发环境可以快速高效地工作。

使用开发环境可以加快经常重复执行的任务,例如:

  • 编译合约
  • 部署合约
  • 调试合约
  • 升级合约
  • 运行单元测试

例如,Truffle 提供以下有用的命令:

  • compile:将Solidity合约编译为其ABI和字节码格式。
  • console:实例化一个交互式JS控制台,你可以在其中调用web3合约并与之交互。
  • test:运行合约的单元测试套件。
  • migrate:将你的合约部署到网络。

Truffle支持提供其他功能的插件。例如,truffle-security提供智能合约安全性验证。 truffle-plugin-verify在区块链浏览器上发布你的合约。你还可以创建自定义插件。

同样,Builder 也有越来越多的插件支持给以太坊智能合约开发人员使用。

无论使用哪种开发环境,选择一套好的工具都是必须。

本地开发

使用Ganache(或Ganache CLI)运行本地区块链进行开发,以“加快迭代周期”。

在主网上,以太坊交易得付费,可能需要数分钟才确认。使用本地链跳过所有这些等待。在本地运行合约交易免费且即时。

Ganache带有一个内置的区块浏览器,可显示你解码后的交易、合约和事件。且本地环境是可配置,以满足你的测试需求。

且设置简便快捷。 在这里下载.

使用静态分析工具

静态分析或“linting”通过运行程序分析代码中的编程错误。在智能合约开发中,这对于捕获编译器可能错过的“代码风格不一致”和“易受攻击的代码”很有用。

1. Linters

使用solhint和Ethlint 分析代码,Solidity的Linter与其他语言(例如JSLint)的linter相似。它们提供安全性和代码风格指南验证。

2.安全性分析

安全分析工具识别智能合约漏洞,这些工具运行一组漏洞检测器,并打印出发现的所有问题的摘要。开发人员可以在整个实现阶段使用此信息来查找和解决漏洞。

可以选择:Mythril·Slither·Manticore·MythX·Echidna·Oyente

额外:使用Pre-Commit Hook

通过使用husky设置Git Hook,使你的开发人员体验变得无缝,Pre-Commit Hook可让你在每次提交之前运行linters。例如:

// package.json
{
  "scripts": {
    "lint": "./node_modules/.bin/solhint -f table contracts/**/*.sol",
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint"
    }
  },
}

上面的代码片段在每次提交之前运行一个预定义的lint 任务,如果代码中存在突出的样式或安全性违规,则会失败。此设置使你团队中的开发人员能够在迭代中与linter一起使用。

了解安全漏洞

编写没有错误的软件非常困难。防御性编程技术只能走这么远。幸运的是,你可以通过部署新代码来修复错误。传统软件开发中的补丁程序频繁且直接。

但是,智能合约是“不可变更的”。有时无法升级已生效的合约。在这方面,智能合约比软件开发更接近于虚拟硬件开发。

更糟糕的是,合约错误会导致巨大的财务损失。 DAO Hack损失了超过1150万以太币(在被黑客入侵时为7000万美元,现在超过了20亿美元),第二名Parity Hack损失了2亿美元的用户资金,现在DeFi领域$ 百亿市场规模一旦出错,损失将非常惨重。

智能合约开发需要与Web开发完全不同的心态。 “快速行动并打破常规”在这里不适用。你需要预先投入大量资源来编写无错误的软件。作为开发人员,你必须:

  1. 熟悉Solidity 安全性 漏洞,和

  2. 扎实理解设计和 模式,例如:付款提取与推送方式 以及遵循 ”检查“ - "更改" - ”交互“等。

  3. 使用防御性编程技术:静态分析和单元测试。

  4. 审计你的代码。

以下各节将详细说明要点(3)和(4)。

初学者提示:你可以使用Ethernauts以交互方式练习Solidity安全性。

编写单元测试

借助全面的测试套件,尽早发现错误和意外行为。不同的场景测试协议可帮助你识别极端情况。

Truffle使用Mocha测试框架和Chai进行断言。你可以使用Javascript针对合约的包装器编写单元测试,就像前端DApp如何调用你的合约。

从Truffle v5.1.0开始,你可以中断测试以对测试流程进行debug并启动调试器,从而允许你设置断点,检查Solidity变量等。

Truffle缺少一些对于测试智能合约必不可少的功能。安装openzeppelin-test-helpers可让你访问许多重要的实用工具以验证合约状态,例如匹配合约事件向前移动时间

译者注: 调试智能合约还有一个选择是使用 Build EVM 及 console.log, 它支持在Solidity源码中打印日志查看变量。

或者,如果你更喜欢使用其他测试运行器,OpenZeppelin测试环境提供了与工具无关的选项。

衡量测试覆盖率

编写测试是不够的。你的测试套件必须可靠地捕获回归。测试覆盖率衡量测试的有效性。

具有较高测试覆盖率的程序在测试期间将执行更多代码。这意味着与覆盖率较低的代码相比,它更容易发现未被检测到的错误。

你可以使用solidity-coverage收集Solidity代码覆盖率

配置持续集成

拥有测试套件后,请“尽可能频繁地”运行它。有几种方法可以实现此目的:

  1. 像我们之前介绍的,设置Git Hook,或者
  2. 设置一个CI(持续集成:Continuous integration) 管道,在每次Git推送后执行测试。

如果你要使用现成的CI,请查看Truffle团队或super blocks.,它们为连续进行智能合约测试提供了托管环境。

托管CI会定期运行你的单元测试,以最大程度地放心。你还可以监视已部署合约的交易,状态和事件。

安全审计合约

安全审计可帮助你“发现”防御性编程技术(linting,单元测试,设计模式)所遗漏的未知问题。

在这个探索阶段,你需要尽最大努力破坏合约, 如:提供意外的输入,以不同的角色调用函数等。

没有什么可以取代人工安全审计,尤其是当黑客入侵的是整个DeFi生态系统时。

️在进行下一阶段之前,你的代码应该已经通过了前面部分提到的静态分析。

聘请外部审计师

聘请(昂贵的)安全审计员来升级以太坊中的主要协议,他们深入研究其代码以发现潜在的安全漏洞。这些审计员结合使用专有和开源静态分析工具,例如:

  • Manticore - 一个模拟器,能够模拟针对EVM字节码的复杂的多合约和多交易攻击。
  • Ethersplay - 一种图形化EVM反汇编程序,能够进行方法还原,动态跳转计算,源代码匹配和二进制比较。
  • Slither - 静态分析器,它检测常见错误,例如重入错误,构造函数,方法访问等。
  • Echidna - 面向EVM字节码的下一代智能模糊器。

审计员将帮助识别协议中任何设计和架构级别的风险,并知道你关于常见的智能合约漏洞。

在该过程的最后,你将获得一份报告,其中总结了审计师的发现...

剩余50%的内容订阅专栏后可查看

  • 单篇购买 10学分
  • 永久订阅专栏 (90学分)
  • 发表于 2020-11-12 14:45
  • 阅读 ( 4515 )
  • 学分 ( 278 )
  • 分类:以太坊
  • 专栏:全面掌握Solidity智能合约开发

评论