草庐IT

安全智能合约工具:端到端开发人员指南

李睿 2023-03-28 原文

​译者 | 李睿

审校 | 孙淑娟

对一些人来说,编写安全智能合约很难。本文将介绍Web3中的一些安全工具,以提高智能合约的安全性。

毫无疑问,编写安全智能合约比较困难,即使是高级开发人员编写的智能合约也可能被黑客攻击。由于这些智能合约通常具有很高的经济价值,因此黑客攻击和破解它们的动机也很高。再加上Web3的不变性,安全性变得更加重要。安全性因此成为了智能合约开发人员的首要任务。

本文将介绍智能合约开发的每个阶段可用的一些安全工具,并对采用这些工具提供一些建议。

1、为开发做好准备

当开始开发智能合约时,安全性应该是开发人员首要考虑的问题,而一些工具可以在准备编写代码时提供帮助,这其中包括文档、检测和编写可重用代码。

首先,文档是任何开发项目的关键,智能合约开发也不例外。以太坊自然规范格式(NatSpec)是一种记录智能合约的好方法。

NatSpec是一种特殊形式的注释,用于为合约、接口、库、函数和事件提供丰富的文档。例如以下Tree Contract的稳定性代码片段:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 < 0.9.0;
/// @title A simulator for trees
/// @author Larry A. Gardner
/// @notice You can use this contract for only the most basic simulation
contract Tree {
/// @notice Calculate tree age in years, rounded up, for live trees
/// @dev The Alexandr N. Tetearing algorithm could increase precision
/// @param rings The number of rings from dendrochronological sample
/// @return Age in years, rounded up for partial years
function age(uint256 rings) external virtual pure returns (uint256) {
return rings + 1;
}
}

NatSpec 对Solidity Contract的注释

通过使用NatSpec注释,可以很容易地向其他开发人员、审核人员或只想与合约交互的人解释代码。简单地说,它是干净的、可读的、容易理解的。

其次,重用经过实战测试的代码是降低智能合约中漏洞风险的另一种经过验证的方法。目前有许多广泛使用的开源智能合约库,例如OpenZeppelin,其中包含用于实现访问控制、暂停功能、升级等的预先编写的逻辑,以及用于优化使用的Solmate合约。

最后,检测是在智能合约代码中发现潜在问题的具有价值的工具。它可以在代码中发现风格错误、违反编程约定和不安全的结构。有很多很好的检测工具可用,例如ETHLint(以前的Solium)。检测可以帮助发现潜在的问题(例如重入漏洞这样的安全问题),甚至在它们成为代价高昂的错误之前。

通过在智能合约开发过程中考虑文档、检测和可重用代码,可以提高合约的安全性。从长远来看,花时间正确地设置这些将会在安全性和效率方面得到回报。

2、开发

现在了解可以在编码时提供帮助的两类工具——单元测试和基于属性的测试。

单元测试显然是创建安全可靠代码的重要组成部分。通过测试代码的单个单元,可以确保合约按照预期的方式运行,并希望在生产中出现问题之前发现任何潜在问题。

有几种不同的工具可用于为智能合约编写单元测试。Foundry、Truffle和Brownie都是支持各种编程语言的流行框架。

Foundry(用Rust编写)是一个用于编写智能合约的框架,其中包括测试框架Forge。伪造单元测试可以直接在Solidity中编写,包括许多欺骗代码,这些代码可以提供断言、改变EVM状态的能力、模拟数据等等。Foundry还带有内置的Fuzzing(将在后面的文章中详细讨论)。

// SPDX-License-Identifier: Unlicense
pragma solidity 0.8.10;
import "ds-test/test.sol";
import "../StakeContract.sol";
import "./mocks/MockERC20.sol";

contract StakeContractTest is DSTest {
StakeContract public stakeContract;
MockERC20 public mockToken;
function setUp() public {
stakeContract = new StakeContract();
mockToken = new MockERC20();
}
/// @notice Test token staking with different amount
function test_staking_tokens() public {
uint256 amount = 10e18;
mockToken.approve(address(stakeContract), amount);
bool stakePassed = stakeContract.stake(amount, address(mockToken));
assertTrue(stakePassed);
}
}

在Foundry中的Solidity单元测试示例

Truffle也是构建智能合约的框架。Truffle中的单元测试可以用Solidity或JavaScript编写。开发人员通常使用基于JavaScript的测试与合同进行外部交互,并使用Solidity测试评估合同在实际区块链上的行为。Truffle使用Mocha进行异步测试,使用Chai进行断言。

Brownie是一个基于python的框架,用于开发和测试智能合约。Brownie与pytest集成用于单元测试,并提供了一个堆栈跟踪分析工具来测量代码覆盖率。

在编写单元测试时,通过测试尽可能多的代码不同部分来实现高测试覆盖率,以确保所有功能都能按预期工作。Foundry不需要额外的插件来测量测试覆盖率。对于其他框架,可能至少可以添加一个插件来衡量这一点。

虽然单元测试是确保智能合约正确性的可靠方法,但基于属性的测试允许对智能合约进行更深入的验证。这是一个相对较新的概念,与传统的单元测试相比,它提供了一系列优势。基于属性的测试侧重于测试智能合约的属性,而不是单个组件。

在指南中,“属性描述了智能合约的预期行为,并声明了关于其执行的逻辑断言。属性必须始终为真。基于属性的测试工具将智能合约的代码和用户定义的属性集合作为输入,并检查执行是否在任何时间点违反了它们。”

基于属性的测试基于模糊概念,这是一种通过引入随机输入来测试系统的技术。这意味着基于属性的测试可以在更广泛的层面上检查智能合约,因为它不依赖于开发人员提供的特定输入。正因为如此,它正成为一种越来越流行的测试智能合约的方法。

以之前的合约为例,使用基于属性的方法来测试一个简单的staking函数。为此,将使用Scribble,这是一种规范语言和运行时工具,它使这一切变得更加容易。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
error TransferFailed();
contract StakeContract {
mapping(address => uint256) public s_balances;
/// #if_succeeds {:msg "Stake created successfully"} $result == true;
function stake(uint256 amount, address token) external returns (bool){
s_balances[msg.sender] += amount;
bool success = IERC20(token).transferFrom(msg.sender, address(this), amount);
if (!success) revert TransferFailed();
return success;
}
}

使用Scribble Notation进行的样品可靠性测试

不同的工具可以使用Scribble规范进行属性测试

为了评估staking函数,必须检查它是否在成功执行的情况下返回true。这可以通过向stake函数代码添加注释来完成,正如上面所表明的那样,不需要单独的测试文件。然后可以运行Scribble CLI工具将Scribble注释转换为断言。接下来,这些断言必须通过模糊器(如Diligence Fuzzing或Mythril)运行,以确定是否存在任何违反属性的情况。

 来自Diligence Fuzzing活动示例的报告

还有一些其他工具可用于基于属性的测试,例如Foundry。Scribble(以上使用的)、Diligence Fuzzing和Mythril是最值得推荐的几种工具。Scribble和Diligence Fuzzing是由ConsenSys Diligence构建的免费开源工具。Mythril是一个旨在检测以太坊智能合约中潜在漏洞的工具。

Scribble这种工具令人喜欢,因为把可这些测试放在一起就像添加函数注释一样简单。

3、后期开发

最后一组工具是后期开发。具体来说,就是监控。

因为大多数区块链上的智能合约代码是不可变的,一旦代码被推送到主网,就几乎无法控制它。监控可以帮助开发人员了解代码中的任何问题或更改,以便可以快速解决它们。这不仅可以帮助开发人员提高合约的安全性,还可以帮助优化和改进其功能。

OpenZepplin的Defender Sentinels和Tenderly的实时警报工具非常适合监控区块链上合约和钱包。

Tenderly Alerts提供了一组自定义触发器以供选择,允许快速设置各种活动的警报,例如部署新合同时、发送或接收事务时以及特定地址时。

Defender Sentinel通过定义的一系列自定义参数提供实时安全监控和警报,例如,如果取款超过特定阈值,如果有人执行关键操作(例如调用转账所有权),或者如果黑名单地址试图与合约交互的时候。

4、结论

智能合约安全工具非常重要。希望本文能够帮助人们了解适合工具,以便编写更安全的智能合约。

原文链接:https://dzone.com/articles/secure-smart-contract-tools-an-end-to-end-develope

有关安全智能合约工具:端到端开发人员指南的更多相关文章

  1. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  2. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  3. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  4. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  5. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  6. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  7. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  8. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  9. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  10. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

随机推荐