智能合约自 20 世纪 90 年代初就存在,这是由著名密码学家尼克·萨博 (Nick Szabo) 设想的。尽管智能合约起源很早,但直到 2015 年以太坊推出后才成为主流。八年后,这些自动执行的合约成为几乎所有其他区块链特定活动的基础。
阅读智能合约就是理解结构和代码块。一定程度的智能合约阅读熟悉度最终为使用 Solidity 编程语言或任何其他特定于平台的语言编写智能合约铺平了道路。但问题并不仅仅在于阅读和编写智能合约。由于智能合约是复杂的去中心化金融(DeFi)协议和去中心化应用程序(DApp)的基础,因此它们必须没有风险和漏洞。智能合约审计可以提供帮助。本指南涵盖了与阅读、编写和审核智能合约相关的所有内容。
在本指南中:
- 阅读智能合约
- 智能合约及其意义
- 智能合约的特点
- 根据特征解读智能合约
- 阅读智能合约的其他部分
- DApp 和智能合约:关系
- 为什么要学习阅读智能合约?
- 如何编写智能合约
- 任何人都可以编写智能合约吗?
- 深入编程
- 编写并部署第一个智能合约
- 智能合约开发和最佳实践
- 如何审计智能合约?
- 审计智能合约的策略
- 如何正确审查代码?
- 非以太坊链和代码审查
- 智能合约审计有哪些不同类型?
- 最佳智能合约审计实践
- 智能合约开发和人工智能:未来
- 经常问的问题
阅读智能合约
智能合约是可编程的代码,仅在满足一组条件时才执行。它们是具有法律约束力的现实世界合同的代名词;只有在这种情况下,代码才是法律。由于智能合约驻留在区块链上,因此它们是不可变的——无法被篡改。正是这种不变性商数使智能合约变得特别。
了解智能合约:基础知识和目的
智能合约旨在自动化区块链特定的交易。由于它们是特定条件的合同,因此不需要中介机构。智能合约之所以有用,是因为它们在广泛的用例中具有兼容性,包括金融服务、供应链管理等。与一次性编程的传统代码块不同,智能合约需要高度安全且耗时的策略。
智能合约如何与区块链技术结合:BeInCrypto
“流行语“web3”暗示了网络松散、安全性差的编程习惯。当加密货币或智能合约像网页一样编程时,它们就注定失败。可持续成功的区块链及其应用程序基于更加安全、仔细和缓慢的编程方法。”
Nick Szabo,密码学家和计算机科学家: Twitter
智能合约可以与区块链特定的代币(例如以太坊区块链的 ERC-20)配合使用,从而激励努力并转移交易。由于涉及代码、条件和成本,您应该小心阅读、编写和审核它们。
智能合约及其意义
智能合约的真正意义在于其本质和定位。对于给定的场景,比如当 A 完成一项服务时,A 将资金转移给 B,区块链节点会保存并执行智能合约的副本。智能合约在链内保存为合约代码。这种多路径验证是一种以区块链为中心的特征,可以确保事物的安全。
此外,还存在顺序或同步智能合约和异步智能合约,其中任务并行执行。因此,智能合约的类型和用途决定了它的编写、读取甚至审计方式。
让我们考虑一个标准的智能合约管理的流动性池。
想象一下,代币池可用于交易,每次成功进行交易时,总交易价值的 0.3% 都会发送给流动性提供者,流动性提供者使交易成为可能或为给定的可交易资产增加流动性。所有强调交易场景、交易费用、违规和交易失败的条件都被编码为智能合约,并以合约代码的形式存储在链内。
智能合约的特点
如果我们不了解合同的特征,我们就无法深入阅读、编写和审计合同。以下是需要注意的标准智能合约特征:
标准智能合约的一些特征:BeInCrypto
可编程合约
智能合约只是一些代码。您可以编写智能合约来根据特定条件执行命令和场景。这就是为什么智能合约开发人员和程序员目前很受欢迎,因为大多数DeFi领域已经依赖智能合约来处理复杂的实例,例如处理跨流动性池的交易费用、维护 APY 比率等。
无需信任
驻留在区块链上的智能合约消除了人为干预。这使他们完全失去信任。例如,如果由智能合约管理的特定 DeFi 协议同意在价值低于阈值时清算您的资产,则任何人为干预都不能或不应该阻止它。该代码处理支付、性能、管理和规则执行,使整个空间完全无需信任。
自主性
如前所述,智能合约加载了自动执行的指令集。就编码而言,这意味着在样板内构建迭代和循环。这确保了诸如支付、提款、存款、通过削减惩罚验证者等任务以及其他一些任务都是自主处理的。
有担保
最后,由于智能合约是使用密码学来保护的,因此破解它们非常困难。如果没有内置漏洞,绕过智能合约就意味着试图在整个区块链面前公开破坏它。
可验证
通过智能合约处理的交易是可自我验证的。这意味着执行足以证明交易首先发生,因为不涉及人为因素。自我验证机制使智能合约比管理遗留银行设置的传统合约更具优势。
因此,下次您计划阅读智能合约时,请确保样板或文档具有所涉及的所有上述特征。
智能合约的简化版本: Reddit
根据特征解读智能合约
这是一个代表托管账户的简单智能合约。用户将资金存入托管机构,然后在特定时间范围后将资金转移到接收方。
// SPDX 许可证标识符:MIT
杂注可靠性^0.8.0;
// 基本智能合约样板
合约 SimpleTrustlessEscrow {
// 状态变量
致公开存款人; // 账户存入以太币
地址应付公共受益人; // 接收以太币的账户
uint256公开发布时间; // 释放以太币的时间戳
// 验证合约活动的事件
事件已存(地址索引 _from,uint256 _value);
事件已发布(地址索引 _to,uint256 _value);
// 合约构造函数初始化智能合约
构造函数(地址应付_受益人,uint256 _releaseTime){
require(_releaseTime > block.timestamp, “发布时间必须是未来”);
// 安全且无需信任:合约约束存款人和受益人
存款人 = msg.sender;
受益人=_受益人;
释放时间=_释放时间;
}
// 存款功能——自主执行(后备功能)
receive() 外部应付帐款 {
发出已存入(msg.sender,msg.value);
}
// 将以太币释放给受益人
函数发布()公共{
// 可编程:只能在releaseTime之后执行
require(block.timestamp >=releaseTime,“发布太早了”);
// Autonomous:根据条件自动执行
uint256 金额 = 地址(this).balance;
受益人.转账(金额);
发出释放(受益人,金额);
}
}
虽然我们将详细解读和阅读此智能合约,但让我们首先检查它是否符合上述合约特征。
“可编程”部分
仔细查看合约中的这段代码:
require(block.timestamp >=releaseTime,“发布太早了”);
uint256 金额 = 地址(this).balance;
受益人.转账(金额);
仅当满足特定的释放时间条件时才会释放资金,从而形成这些可编程合约。
“不信任”部分
这是上面的快速代码片段:
存款人 = msg.sender;
受益人=_受益人;
释放时间=_释放时间;
在合同中,从存款人到接收资金的人,每个人都受到代码约束。没有人需要与对方交互或信任对方,因为转移资金的功能受到releaseTime(一种基于代码的参数)的约束。
“自主”部分
这是代码的“资金释放”部分:
函数发布()公共{
require(block.timestamp >=releaseTime,“发布太早了”);
uint256 金额 = 地址(this).balance;
受益人.转账(金额);
发出释放(受益人,金额);
}
整个过程是自主的,因为只有当释放时间满足一定标准时才会释放资金。请注意,代码不是部分可编程的,而是完全自主的。
智能合约代码的其他元素(包括存款功能)也可以完全自主,具体取决于您想要包含的功能。例如,每当用户的钱包超过 100 美元时,您就可以启动定期存款计划,多余的金额将转移给受益人。
“安全”部分
关心哪个要素为合同提供担保?查看这部分代码:
构造函数(地址应付_受益人,uint256 _releaseTime){
require(_releaseTime > block.timestamp, “发布时间必须是未来”);
存款人 = msg.sender;
受益人=_受益人;
释放时间=_释放时间;
}
请注意,releaseTime 函数相对于时间戳是如何设置优先级的。没有什么是随机的,必须满足条件。
“可验证”部分
与智能合约相关的每笔交易都记录在链中,由单独的日志活动元素提供。
事件已存(地址索引 _from,uint256 _value);
事件已发布(地址索引 _to,uint256 _value);
发出已存入(msg.sender,msg.value);
发出释放(受益人,金额);
阅读智能合约的其他部分
现在我们已经确定了定义智能合约特征的元素,下面是其他合约元素,可以帮助您更好地理解演练。
杂注可靠性^0.8.0; – 编写此智能合约所需的 Solidity 编程语言版本。
// SPDX-License-Identifier:MIT – 术语“软件包数据交换”,该标识符表示代码发布的许可证。建议包含此内容,以便让人们知道它是否是开源的并且可以解决。
Contract TimeLock { – 为智能合约分配名称,就像标签一样。
致公开存款人; – 由于合同涉及存款人和受益人,因此这里提到了存款人的公共地址。该变量是以太坊钱包地址,并且是公开可见的。
应付公共受益人地址; – 这是托管机构转移资金的受益人的公共地址。它也是可读的,并为区块链驱动的智能合约带来了透明度。
Uint256公开发布时间; – 由于它是有时限的合同,因此 uint256 将基于时间的变量分配给合同。这将是基金发行的时间表。
在 Solidity 中,uint(无符号整数)是分配基于整数的值的方法。后缀256代表大量数字存储。
您可以考虑阅读Solidity 文档来熟悉语法、表达式和其他代码元素。
其他元素
constructor(address payable _beneficiary, uint256 _releaseTime) { – “Constructor”是一个一次性特殊函数,在部署智能合约时被调用。它启动了合同。请注意,此时我们之前声明的所有地址变量都被调用并初始化。
Receive() external payable { – 这是资金从外部转移到合约地址时调用的特殊函数。外部建议来自外部,“Payable”定义了此举的性质,即接收ERC-20代币。
Function release() public { – 这是一个公共函数,用于说明 ERC-20 代币从合约地址到受益人的移动。该功能取决于releaseTime。
所有这些要素都是我们讨论的假设托管合同的一部分。确保您阅读完整的 Solidity 文档,以便更好地了解该语言。
在计划编写智能合约之前了解这些要素:BeInCrypto
DApp 和智能合约:关系
到目前为止,您应该在阅读和理解已经编写的智能合约方面取得了先机。许多智能合约(例如我们讨论的智能合约)构成了去中心化应用程序的后端——标准移动应用程序的区块链版本。
智能合约的每一个特性,包括合约安全性、自主和可编程执行、交易的去信任性等等,在开发去中心化应用程序时都很容易实现。因此,下次您偶然发现 DApp 时,请注意,它是托管在区块链上的智能合约驱动的后端,可帮助您在无需人工干预的情况下启动多个任务。智能合约构成了 DApp 的逻辑。
智能合约的区块链
我们知道以太坊可以让您开发智能合约,就像大型软件解决方案一样。然而,它并不是唯一的区块链协议。如果您想深入了解智能合约开发的世界,您可能想看看其他区块链。不同的区块链在制定合同时有不同的说法。
但首先,让我们讨论一下以太坊——大多数智能合约开发人员的首选平台。
以太坊
以太坊上的智能合约是用 Solidity 编程语言编写的。该智能合约开发平台的代币接口是ERC-20。
您可以回到我们之前讨论的基于托管的智能合约,看看标准的基于以太坊的智能合约是如何编写的。
即使在以太坊区块链上启动 ERC-20 代币也是一项智能合约密集型功能,我们将在编写智能合约时深入讨论这一点。
如果我们计划推出新的加密货币 BIC,则基本代码结构如下所示。
将此视为假设场景。不完全是推出 BIC 加密货币。
pragma Solidity ^0.8.0;import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;合约 BICToken 是 ERC20 { 构造函数(uint256 initialSupply) ERC20(“BIC Token”, “BIC”) { _mint(msg.sender) ,初始供应); }}
稍后在编写智能合约时我们将讨论该代码的每个元素。
其他区块链
与以太坊一样,您甚至可以在Solana等平台上使用 Rust 和 Cardano、Plutus(函数式编程语言 Haskell 的子集)创建智能合约。
Rust (Solana) 中的代码结构如下所示:
注意:这是一个简单的合约,其中计数器会递增。
使用anchor_lang::prelude::*;
声明_id!(“Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS”);
#[程序]
酒吧模组 hello_world {
使用超级::*;
pub fn 初始化(ctx: Context<Initialize>) -> ProgramResult {
让greeting_account = &mut ctx.accounts.greeting_account;
问候帐户.计数器 = 0;
好的(())
}
pub fn 增量(ctx: Context<增量>) -> ProgramResult {
让greeting_account = &mut ctx.accounts.greeting_account;
greeting_account.counter += 1;
好的(())
}
}
你可知道? Rust 是用于创建基于 Solana 的智能合约的编程语言,而 Anchor 是所使用的智能合约开发框架。为了使用 Rust 创建智能合约,开发人员需要从 Anchor 框架中提取模块——我们示例代码的第一行 (useanchor_lang::prelude::*;) 所代表的内容。
Solana 文档将帮助您了解 Rust 特定的智能合约语言。
同样,Cardano 紧随 Plutus 作为语言选择,其次是 Ink! Polkadot的语言、Algorand 的 TEAL、NEO 的 C# 等等。在继续编写兼容的智能合约之前,建议详细学习链式文档。
为什么要学习阅读智能合约?
编写智能合约的能力得到了高度认可,但即使能够阅读也有其好处:
- 能够了解与 DeFi 应用相关的自动化复杂性。
- 分析与资产代币化相关的所有权标准。
- 了解去中心化自治组织 (DAO) 的运作方式。
- 了解并实施与保险、内容货币化、投票系统、版税和其他垂直领域相关的用例驱动逻辑。
如何编写智能合约
现在阅读智能合约已经不再困难,让我们专注于编写智能合约。在深入研究之前,有必要重申不同的区块链可能有不同的与智能合约开发相关的标准和语言。有必要关注任何给定区块链定义的标准,从编写和合约部署开始。
在我们的大部分讨论中,我们将重点关注作为链的以太坊和作为语言的 Solidity。
编程的作用
智能合约编程无疑是开发周期中最重要的部分。要进入以太坊或任何其他区块链上的智能合约开发,您应该对非区块链编程语言(如 Javascript)有一定的经验。
不同的区块链和编写智能合约的语言:BeInCrypto
编写智能合约的能力使您能够实现逻辑、处理相同的安全元素、优化汽油费代码、自定义相同的代码,甚至在需要时使相同的代码具有互操作性。
EVM 和智能合约:基础知识
任何计划在以太坊上编写智能合约的人都需要了解以太坊虚拟机(EVM)是什么以及它如何与智能合约配合使用。首先,EVM 是一个以太坊组件,为程序提供了一个隔离且受控的工作环境。将其视为托管以太坊上每段合约代码的全球计算机。以太坊网络上的每个节点都运行 EVM。
如果您有志成为一名智能合约开发人员,以下是您需要了解的有关智能合约和 EVM 的知识。
一旦你用 Solidity(一种高级语言)编写了程序,你就需要将其编译成字节码——一种机器可理解的低级格式。该字节码进入以太坊区块链并驻留在其中。任何与智能合约交互的人都需要将交易发送到合约地址。
每个安装了 EVM 的节点都可以看到该交易,一旦验证者批准该交易,智能合约代码就会被执行。由于每个节点都具有事务可见性,因此任何内容都无法篡改,并且代码按编写时执行。一旦代码被执行,区块链的状态就会发生变化,使该过程端到端且完全透明。
任何人都可以编写智能合约吗?
编写智能合约需要技术知识。但事实并非如此。您还需要彻底了解区块链技术的工作原理、哪些特定于语言的需求与您所针对的区块链相关、互操作性等等。除此之外,您还应该了解有关智能合约漏洞的大量信息——编写代码时要避免的事情。最后,合约测试和合约部署知识也是必须的。
所有这些都可能变得势不可挡。所以这是一个快速入门的备忘单:
- 首先选择您想要合作的平台或连锁店。
- 学习与链相关的编程语言,例如以太坊的 Solidity。
- 了解如何使用 Remix 等集成开发环境等开发工具。
- 首先编写您的第一个合约,然后使用测试网进行测试。
- 一旦您对代码的元素感到满意,您就可以将其部署到链上。请记住,在链上部署合约将以天然气费的形式产生费用。
这是一个快速主题,其中包含一些编写更好的智能合约的技巧:
深入编程
现在是时候讨论智能合约开发的技术方面了。尽管像 Solana 和 Cardano 这样的链允许您开发智能合约,但以太坊仍然是最受欢迎的智能合约开发平台。
你可知道?仅在 2022 年,就有超过 100,000 个去中心化应用程序进入以太坊网络。
为什么是以太坊?
以太坊拥有庞大的开发者社区。你开发的任何东西都会立即引起注意。另外,它的母语 Solidity 对于了解 Python 或 JavaScript 的人来说相对容易。最后,以太坊全球软件 EVM 有助于无缝执行合约。
第一份合同的 Solidity 基础知识
如果您是大多数人并且更喜欢使用以太坊和 Solidity,那么在开始智能合约开发之前,您需要跟踪以下事项的快速列表:
- 编译指示或编译器版本
- 标签合同定义
- 用于存储数据的状态变量
- EVM 日志记录事件
- 赋予特定机构特定权利的修改者
- 正在发挥作用的功能或智能合约活动
- 互操作性的继承
- 了解 if、else、for 循环等控制结构,以及字符串、整数等数据类型。
编写并部署第一个智能合约
现在我们知道事情在链上是如何进行的,让我们开始编写和部署第一个智能合约。尽管“Hello World”仍然是第一步,但我们将首先创建一个智能合约,以推出一个假设的 BIC 代币,其供应量为 100 万个 100% 解锁。
基础
第一步是安装最新版本的 Node.js 和 NPM 或 Node Package Manager。这会照顾到开发工具和本地开发环境。此外,Node.js 和 NPM 允许您为智能合约设置 Web 前端。
现在,您需要设置一个IDE来编写合约代码。为此,您可以快速安装 Visual Studio Code。或者,您也可以摆脱混乱,转向 Alchemy——一个区块链开发平台。通过 Alchemy,您可以获得一些测试网 ETH。当您将智能合约部署到 Goerli 测试网甚至 Sepolia 测试网时,这将涵盖 Gas 费用。
请注意,Sepolia 是一个较年轻的测试网,因此在节点部署方面占用的磁盘空间较少。
目前,我们将继续使用 Goerli 测试网,因为它拥有大量已部署的应用程序。
测试网和假 ETH 准备就绪后,让我们开始专门编写智能合约。以下是创建固定供应量 100 万个 BIC 代币的代码片段。
注意:我们将在 MacOS 本地部署智能合约,而不是测试网上。对于智能合约的测试网和主网部署,我们将有一个单独的部分,这超出了本讨论的范围。
编写和部署的步骤
这是假设令牌的简单代码片段:
pragma Solidity ^0.8.0;import “@openzeppelin/contracts/token/ERC20/ERC20.sol”;合约 BICToken 是 ERC20 { constructor() ERC20(“BIC Token”, “BIC”) { _mint(msg.sender, 1000000 * 10 ** 小数()); }}
如果您了解语法,您就会知道每个代码组件的含义。至于Openzepplin部分,它是导入ERC-20智能合约的首选库。该库提供了 ERC-20 代币的基本操作标准。
mint 函数讨论初始供应,该供应被部署到智能合约地址或 msg.sender。
要在本地设置此代码并进行测试,我们需要三个组件:
- Node.js 和 NPM(已经讨论过):像引擎一样为您的智能合约提供动力
- Truffle:像工具箱一样工作,帮助您组织代码、脚本和合同的其他部分
- Ganache:就像设备上的虚拟游乐场一样。将其视为个人区块链。
什么是合同执行?
如果您已经完成了编写智能合约的详细过程,那么有必要了解一些有关合约执行的知识。它是节点在链上执行智能合约代码的过程。
正是与合约执行相关的一致性使得智能合约透明且不可变。现在让我们了解与合同执行相关的分步流程:
步骤1
我们编写的代码片段需要在某个地方执行。就智能合约而言,执行地点就是区块链。节点或链上的参与成员帮助执行合约。
第2步
节点承担执行合约代码块的责任,以换取与链相关的激励。链内发生的每一个命令或动作都由智能合约主导。
步骤3
每个智能合约都有一个特定的地址。为了执行合约,交易被发送到该合约地址。请注意,每个节点都运行 EVM,然后 EVM 拥有智能合约代码的副本,从而更容易检查交易的真实性。
步骤4
针对智能合约的交易由验证者挑选,然后将其包含到特定的区块中。
步骤5
一旦交易被推送并成功验证,它就成为区块链的一部分。然后,与交易相关的智能合约函数在区块链节点上被调用并执行。
步骤6
执行智能合约的每个节点都应该得出确定性结论——同一组输入具有相同的输出——从而使合约的性质完全去信任和透明。
注意:任何与代码执行有关的错误或与汽油费相关的问题都会撤销交易。这意味着基于特定智能合约代码的交易将不复存在。这正是闪电贷发生的情况,因为无法遵守特定规范而导致整个交易发生逆转,似乎给人一种资金从一开始就没有流动的印象。
与智能合约相关的每个状态变化都会记录在区块链中,并成为区块链的不可变部分。
智能合约开发和最佳实践
现在您已经对智能合约有了一定的了解,下面是一些开始合约开发的建议:
- 在编写合约时,建议依赖 OpenZeppelin 等受信任的库来遵守所需的代码优化和安全标准。
- 其想法是保持合同模块化和简单化——使其更容易测试和审查。
- 一个好主意是实施特定于合约的访问控制。这意味着声明只有特定个人或实体才能更改合约关键特征的代码位。访问控制可以更轻松地保证智能合约的安全。
- 在编写合同时,始终要制定处理边缘情况和异常的规定——同时编写多个测试。
照顾代码的可持续性
上面提到的每个实践都有助于代码优化和特定于安全性的实现。但是,您必须遵循和实施一些特定于合同的实践,以保证代码的可持续性。这样做的目的是保持合约代码轻便且可用,以便每个运行和执行相同代码的节点不必为其投入大量计算能力。
- 通过使用较小的数据集有效地处理存储。例如,在编写合约时,使用 uint8 作为操作值而不是 uint256。
- 在编写合约时,建议通过将多个操作合并为一个操作来优化代码。我们将在“编写智能合约”的详细文章中更深入地探讨这一点。
- 一个好主意是在智能合约执行方面使用惰性评估。这样,您只需在需要时执行一个函数,而不是每次将某些内容推送到智能合约地址时执行。
- 最后,依靠链下计算也是关注可持续性的好方法。这有助于降低汽油费要求,甚至可以加快合同执行速度。
尽管在编写和开发智能合约时遵循了最佳实践,但在将其推送到主网时仍需要关注合约安全漏洞。
如何审计智能合约?
主网中存在的每个智能合约都需要评估代码性能、安全性和其他特征。这就是审计(严格的合同测试流程)脱颖而出的地方,让您能够发现潜在的合同漏洞和弱点。
以下是一个快速入门的审核清单:
阅读、写作和审计之间的关系:为什么还要审计智能合约?
虽然在开发智能代码时,阅读和编写智能合约是相互交织的,但审计具有特殊的地位,并且首先涉及检查逻辑。当涉及基于区块链的代码执行时,一切都是不可变的,任何灾难性的事情都可能对合约执行产生不可逆转的后果。这正是为什么需要通过审计对合同代码和其他方面进行彻底检查。
合约漏洞及修复
详细的智能合约审计可以识别出许多合约漏洞。其中包括检查重入攻击、溢出或下溢、与访问控制相关的问题等等。一旦确定了问题的确切性质,审计员甚至可以建议解决该问题的最佳实践。
违规演员研究和学习
仍然不确定智能合约审计有何帮助?好吧,让我们回顾一下 2016 年臭名昭著的 DAO 黑客事件,该事件利用了重入问题,造成了近 360 万 ETH 的损失。同样,2017 年 Parity 钱包合约被黑客攻击,导致近 50 万 ETH 损失。通过正确的审核,这些问题本来可以避免。
DAO 黑客流程图:BeInCrypto
审计智能合约的策略
审计智能合约的策略有很多。一些较受欢迎的包括:
审核工具
这些工具充当第一套防御措施,最适合用于定位常见漏洞。一些更流行的工具包括 Securify、Mythril 等,能够对代码执行静态分析、检测违规模式并帮助获得特定于安全性的领先优势。
审计智能合约的工具:BeInCrypto
代码审查
这就是手动代码审查人员介入的地方,检查代码库并识别复杂的漏洞(如果有)。手动审查可以帮助处理业务逻辑、上下文和使用模式。
以下是手动代码审查如何帮助您定位威胁:
自动扫描
Snyk 和 GuardRails 等工具有助于自动合同扫描——每次更新代码时都会调用的安全实现。这种形式的审计可确保对代码所做的新更改本质上是安全且非侵入性的。
形式验证
这是一个复杂的过程,仅依赖于检查代码的业务逻辑。请注意,形式验证实际上并不是为了验证语法,而是为了验证代码是否按预期执行的逻辑。
除了上述策略之外,还可以使用同行评审、错误赏金计划和通过 Solidity Coverage 等工具进行测试覆盖率来启动智能合约审计,以最大限度地提高效率。
审计智能合约的简单方法:BeInCrypto
如何正确审查代码?
如果您是智能合约审计的新手,请务必注意,有两种方法可以广泛分析代码和识别问题。这些包括:
静态分析
这种类型的代码分析有助于根据给定的编码标准和约定识别基本的安全漏洞、编码错误和其他问题。可以使用静态分析来突出显示未经检查的对外部源的调用、整数溢出等威胁。静态分析的最大好处是不需要执行代码就可以对其进行检查。
动态分析
这种审计方法测试代码与 EVM 的一致性。动态分析不是仅检查代码,而是交叉检查智能合约对各种输入的响应。动态分析可以识别诸如不连贯的 Gas 消耗甚至错误的合约逻辑等问题。像 Ganache 这样的个人区块链环境可以用作动态分析平台,允许开发人员进行交易、执行命令以及使用合约执行更多操作。
测试一段实际的代码
这是一个智能合约片段,用作资金存储,具有提款功能:
pragma Solidity ^0.6.1;contract VulnerableContract { 映射(地址 => uint256)公共余额; function Deposit() public payable { 余额[msg.sender] += msg.value; } functionwithdraw(uint256 _amount) public { require(balances[msg.sender] >= _amount, “余额不足。”); (bool success, ) = msg.sender.call{value: _amount}(“”); require(success, “传输失败。”);余额[msg.sender] -= _amount; }}
如果仔细观察代码,会发现一个关键漏洞:
在前一种情况下,如果接收资金的用户也是智能合约,则可以再次调用“取款”函数,尽管是恶意的。因此,在最后一个函数或余额更新发生之前,可以发起重入攻击以转移额外的资金。经验丰富的审计员可以识别这种漏洞。
这是相同的固定代码:
functionwithdraw(uint256 _amount) public { require(balances[msg.sender] >= _amount, “余额不足。”);余额[msg.sender] -= _amount; (bool success, ) = msg.sender.call{value: _amount}(“”);
require(成功,“传输失败。”);
}
检查如何首先调用余额更新函数,然后首先调用用户。操作顺序的改变就是修复合同的原因。
非以太坊链和代码审查
去中心化应用程序和智能合约的世界已经超越了以太坊。尽管大部分操作仍然发生在以太坊生态系统内,但还有其他链(例如 Cardano、Solana 等)支持智能合约并需要不同的审计标准。
为什么每个平台都是独一无二的?
不同的区块链使用不同的编程语言。代码的语义、语法和属性不同,使得智能合约能够响应不同的编写和审计实践。例如,以太坊使用 Solidity,而Polkadot使用 Ink 和 Rust——使其对特定的审计标准做出反应。
非以太坊的工具
现在,如果您想超越以太坊,有一些专门的审计工具可以帮助您入门。例如,卡尔达诺有用于形式验证和审计的马洛套件。对于 Solana,Rust 特定的 libfuzzer 和 Cargo-fuzz 旨在用于审计和合同测试。多链审计员必须熟悉这些概念,以防止合约漏洞。
智能合约审计有哪些不同类型?
重申一下,您可以将智能合约审计分为三种类型:手动、自动和混合。请注意,人们更喜欢针对具有深层业务逻辑的复杂合同的混合审计策略,因为它们是最全面的。
外包您的审计
具有最少编码知识的组织和个人通常将其写作和审计要求外包给知名公司。在审计方面,选择合适的公司变得更加重要,因为尽管ChatGPT等人工智能工具可以帮助编写智能合约代码,但检查同样需要手动洞察。
另外,外包审计任务时需要注意以下因素:
选择合适的公司
在您选择合适的外包公司之前,检查过去的审计、评估经验,甚至关注关键团队成员是至关重要的。
了解责任、成本和管理费用
在雇用之前,请注意与审计相关的成本和服务。必须首先了解所提供服务的性质,例如问题识别、问题解决等。您还必须检查实施第一行修复后是否还提供重新审核。智能合约审计的成本可能因服务而异,因此,有必要在继续之前跟踪每项要求和产品。
最佳智能合约审计实践
如果您想放弃一家公司并亲自审核智能合约,请记住以下最佳策略和实践:
- 始终专注于彻底的代码审查,包括语法和逻辑
- 首先使用 Slither、MythX 等工具找出常见漏洞
- 浏览智能合约漏洞分类注册表或 SWC,找到已知漏洞并提前检查。
- 对智能合约进行严格的测试,包括集成测试、单元测试等,以在各种场景下对代码进行压力测试。
- 特别检查重入攻击的可能性非常重要。解决这个问题的最佳方法是检查黑客在第一个智能合约函数之前可以调用的递归调用。
- 重点关注导致外部调用的函数。这方面的错误可能会改变状态和控制流,这是不希望的。
- 始终关注指向 Gas 使用情况的代码位。您不希望您的合约发起成本过高的交互。
智能合约开发和人工智能:未来
人工智能确实使编写智能合约变得更加容易。然而,无论人工智能如何创新,以最佳方式审计智能合约的能力仍然需要人工干预。因此,如果您计划构建下一个强调智能合约和去中心化应用程序的 web3 产品,那么专注于智能合约的最佳审计资源至关重要。随着加密货币黑客攻击和违规行为日益增多,黑客们也在计划新的突破策略,对合同进行完美审计无疑是当今更重要的技能之一。
经常问的问题
智能合约是如何编写的?
如果您想编写智能合约,您必须首先了解如何使用 JavScript 或 Python 等高级编程语言编写逻辑。或者,如果您知道如何使用 Solidity(以太坊的原生编程语言)进行编码,这会有所帮助。一旦逻辑正确,您需要仔细编写语法并包含修饰符、函数、变量等编码元素。
智能合约是用什么语言编写的?
虽然 Solidity 是一种常见的智能合约语言,但它主要与以太坊生态系统相关。如果您想与 Polkadot、Cardano 和 Solana 等其他链进行交互,您可以使用 Rust、Ink 甚至 Plutus 等。需要注意的是,不同的区块链支持不同的区块链开发语言,这可能会改变您编写和审核智能合约的方式。
智能合约是用可靠的语言编写的吗?
基于以太坊的智能合约是用 Solidity 编写的。值得注意的是,Solidity 是一种面向契约的语言,与 JavaScript、Python 甚至 C++ 相似。然而,如果您想为您的智能合约探索 Cardano 和 Solana,其他 Solidity 并不是首选的智能合约语言。
智能合约如何审计?
审计智能合约需要仔细查看合约代码,检查其漏洞,并在测试网上进行测试。主网上的合约测试可能会产生高额的 Gas 费。此外,还需要静态和动态智能合约分析,然后依赖自动化工具、手动审查和常见漏洞检查。
如何从智能合约中读取数据?
从智能合约读取数据涉及使用区块链浏览器、API,甚至 web3 库。这些工具能够与链交互并从状态变量中检索数据。您甚至可以使用 ABI 或应用程序二进制接口从合约中读取数据,这将为您提供合约功能的 JSON 表示形式。
在智能合约开发的初始阶段会进行什么类型的审计?
审计师大多在智能合约开发的初始阶段进行白盒审计。这种类型的审核也称为透明盒审核或透明盒审核。这里的想法是审查和测试逻辑和代码的设计、结构和实现。智能合约的白盒审计还验证功能并对代码进行合约安全分析。