第1章:区块链基础与EVM原理

各位同学,欢迎来到智能合约安全审计的第一课。

说实话,我见过太多人一上来就写合约,结果连区块链的基本概念都没搞清。嗯,这就像没学会走路就想跑马拉松。今天,我们先把地基打牢。

1.1 区块链核心概念回顾

区块链是什么?说白了,就是一个分布式账本。每个人手里都有一份相同的账本,谁也别想偷偷改数据。

我个人习惯把区块链理解成「一串用密码学锁链连接的数据块」。每个块里装着交易记录,块与块之间通过哈希值链接。你改一个块,后面的所有块都得改,这在算力上几乎不可能。

核心三要素:

  • 去中心化:没有单点故障,没有中央服务器
  • 不可篡改:数据一旦上链,几乎无法修改
  • 透明可追溯:所有交易公开,谁都能查

我在项目中遇到过不少新手,以为「区块链就是数据库」。其实差别很大。数据库可以删改,区块链只能追加。你想想看,这特性对智能合约意味着什么?——代码一旦部署,想改?难了。

1.2 以太坊虚拟机(EVM)架构

EVM,全称 Ethereum Virtual Machine。你可以把它想象成一个全球共享的超级计算机。这台计算机不跑在某个机房,而是跑在成千上万个节点上。

EVM 的核心特点:

  • 图灵完备:理论上能计算任何可计算的问题
  • 沙箱隔离:合约之间互不影响,出问题只影响自己
  • 确定性执行:同样的输入,在任何节点上都得到同样的输出

为什么会强调确定性?因为如果不同节点算出的结果不一样,整个网络就分裂了。我刚开始学的时候,总觉得这限制太多,后来才明白——没有确定性,就没有共识

EVM 的存储结构

EVM 里有三种存储区域,你得记清楚:

存储类型 特点 成本 生命周期
Storage(存储) 永久存储,写入链上 最贵(20,000 Gas+) 合约生命周期
Memory(内存) 临时存储,函数执行期间有效 较便宜 函数调用期间
Stack(栈) EVM 操作栈,深度 1024 免费(但有限制) 指令执行期间

避坑指南:我曾经审计过一个合约,开发者把大量数据存在 Storage 里,结果每次调用都花天价 Gas。记住:能用 Memory 就别用 Storage,能用事件就别存变量。

1.3 交易与消息调用

在以太坊上,一切动作都始于交易。交易分两种:

  1. 普通转账:从 A 地址转 ETH 到 B 地址
  2. 合约调用:调用合约里的某个函数

消息调用呢?就是合约之间互相「说话」。比如合约 A 调用合约 B 的函数,这就是一次消息调用。注意,消息调用不产生新的交易,它是在同一笔交易内部发生的。

安全警告:消息调用是重入攻击的温床。我曾经审计过一个 DeFi 项目,攻击者就是利用合约间的消息调用,反复调用提现函数,把池子掏空了。后面讲重入攻击时,我们会详细拆解。

交易的结构

一笔交易包含这些字段:

  • nonce:发送方的交易序号,防止重放攻击
  • gasPrice:你愿意为每单位 Gas 付多少钱
  • gasLimit:你愿意为这笔交易花多少 Gas
  • to:目标地址(合约或外部账户)
  • value:转账金额(单位:wei)
  • data:调用数据(合约调用时携带的函数签名和参数)
  • v, r, s:签名信息,证明交易是你发的

嗯,这里有个坑。很多人以为 gasPrice 越低越好,省钱嘛。但 gasPrice 太低,矿工不打包,交易可能卡几个小时甚至几天。我建议你根据网络拥堵情况动态调整,别省那点钱耽误事。

1.4 Gas 机制详解

Gas 是以太坊的「燃料」。每执行一条指令,都要消耗一定量的 Gas。为什么要设计 Gas?防止死循环。如果没有 Gas 限制,一个恶意合约可以让全网节点无限循环,那整个网络就瘫痪了。

Gas 的计算公式很简单:

交易费用 = gasUsed × gasPrice

其中:

  • gasUsed:实际消耗的 Gas 量
  • gasPrice:你愿意支付的单价(单位:gwei)

1 ETH = 10^9 gwei = 10^18 wei

常见操作的 Gas 消耗

操作 Gas 消耗 说明
转账(基础) 21,000 最简单的 ETH 转账
SLOAD(读存储) 2,100(热) / 2,100(冷) 读取 Storage 变量
SSTORE(写存储) 20,000(新写) / 5,000(修改) 写入 Storage 变量
合约创建 32,000 + 部署代码 Gas 部署新合约
SHA3(Keccak256) 30 + 6 × 数据长度 计算哈希

关键点:写 Storage 比读 Storage 贵 10 倍。读 Storage 比读 Memory 贵 100 倍。所以,能缓存就缓存,能压缩就压缩。我在审计中经常发现,很多 Gas 浪费都是因为开发者没注意这些细节。

Gas 上限与区块 Gas Limit

每个区块都有 Gas Limit,目前以太坊主网大约是 30,000,000 Gas。这意味着一个区块能容纳的交易量是有限的。如果网络拥堵,交易就得排队。

你可能会问:那我设置 gasLimit 越高越好吗?不是。gasLimit 是你愿意为这笔交易支付的最大 Gas 量。如果实际消耗超过 gasLimit,交易会回滚,但 Gas 不会退还。所以,别设得太低,也别设得太高。

我的经验:对于普通转账,gasLimit 设 21,000 就够了。对于合约调用,我一般设 100,000 起步,复杂操作设 500,000。如果拿不准,可以用 ethers.js 的 estimateGas 方法先估算一下。

知识体系总览

下面这张图,是我自己整理的本章知识结构。你可以把它当作学习地图:

区块链基础与EVM 区块链核心概念 去中心化 · 不可篡改 透明可追溯 EVM 架构 Storage · Memory · Stack 沙箱隔离 · 确定性 交易与消息调用 普通转账 · 合约调用 消息调用 · 重入风险 Gas 机制 gasUsed × gasPrice 存储读写成本差异 安全审计视角 Gas 浪费 · 重入攻击 存储优化 · 交易验证 打好基础,才能写出安全的合约

这张图把本章的核心知识点串起来了。你看到没?所有内容最终都指向一个目标——写出更安全的合约。区块链基础决定了你的认知边界,EVM 原理决定了你的代码质量,Gas 机制决定了你的合约成本。三者缺一不可。

好了,第一章就到这里。记住我今天说的:基础不牢,地动山摇。下一章我们开始动手写合约,到时候你会感谢今天打下的基础。


公众号:蓝海资料掘金营,微信 deep3321