2、区块链基础回顾:以太坊与EVM、账户与交易、Gas与手续费、钱包与私钥管理

好,咱们正式开始技术内容之前,先花点时间把区块链的基础再过一遍。我知道有些同学可能已经接触过以太坊,但别急,我保证这一章讲的东西,跟你平时看到的那些科普不太一样。我会结合自己踩过的坑,把那些看似简单、实则容易出问题的地方掰开揉碎了讲。

2.1 以太坊与EVM:不只是“世界计算机”

以太坊是什么?很多人张口就来——“世界计算机”。嗯,这个说法没错,但太笼统了。我个人习惯把它理解成一个全球共享的、确定性的状态机

什么叫状态机?说白了,就是整个网络有一个全局状态,每出一个新区块,状态就更新一次。而这个状态转换的规则,就是由EVM(以太坊虚拟机)来执行的。

EVM其实是个很轻量的东西。它不像你的电脑有Windows或者macOS,它只认识一套特定的字节码指令。你写的Solidity代码,最终会被编译成这些字节码,然后部署到链上。每次有人调用你的合约,EVM就会逐条执行这些字节码,更新状态。

关键点:EVM是确定性的。同样的输入,在任何节点上执行,结果必须完全一样。这也是区块链能达成共识的基础。我在早期做跨链桥项目时,就因为忽略了不同EVM实现之间的微小差异,导致两边状态对不上,排查了整整两天。

这里有个概念容易混淆:以太坊不等于EVM。以太坊是主网,EVM是它的执行引擎。现在很多公链(比如BSC、Polygon、Avalanche)都兼容EVM,这意味着你写的Solidity合约,稍微改改甚至不改,就能部署上去。但要注意,兼容EVM不代表完全一样,底层的共识机制、区块时间、Gas模型都有区别。

2.2 账户与交易:两种账户,一种规则

以太坊上有两种账户:外部账户(EOA)合约账户。这个区分非常重要,我见过不少新手在这上面翻车。

特性 外部账户(EOA) 合约账户
谁控制 私钥持有者 合约代码逻辑
能否发起交易 不能(只能被调用)
是否有代码 有(合约字节码)
存储 只有余额 有存储空间(Storage)

你想想看,为什么合约不能主动发起交易?因为合约没有私钥。它的一切行为,都是被外部账户或者其他合约“触发”的。这也是为什么很多DeFi协议需要“ keeper ”或者“ 机器人 ”来定时调用某些函数——合约自己没法起床干活。

交易的结构,我直接给你看最核心的字段:

{
  "nonce": 5,           // 该地址发起的交易序号,防重放
  "from": "0xAbc...",   // 发送方
  "to": "0xDef...",     // 接收方(如果是部署合约,这里为空)
  "value": 1000000000000000000, // 1 ETH,单位wei
  "gasLimit": 21000,    // 最大允许消耗的Gas
  "maxPriorityFeePerGas": 2000000000, // 小费,单位wei
  "maxFeePerGas": 50000000000,        // 你愿意支付的最高Gas价格
  "data": "0x..."       // 调用数据(转账时为空)
}

这里有个坑,我必须要说。nonce 是严格递增的,而且不能跳号。如果你发了一笔 nonce=5 的交易卡住了,那么 nonce=6、7、8 的交易都得排队等着,哪怕你换一个接收方也没用。我曾经在测试网调试时,不小心把 nonce 搞乱了,结果后面几笔交易全部卡死,只能等那笔卡住的交易超时或者被替换。

避坑指南:如果你发现某笔交易一直 pending,不要急着重发相同 nonce 的交易。先检查一下 nonce 是否被占用。用 ethers.js 的 getTransactionCount() 方法可以查到当前地址的 nonce 值。

2.3 Gas与手续费:为什么你的交易会失败?

Gas 是以太坊上最让人头疼,但也最核心的概念。简单说,Gas 是衡量计算工作量的单位。你每执行一条指令,EVM 都会消耗一定量的 Gas。

手续费的计算公式:

交易手续费 = Gas Used × (Base Fee + Priority Fee)
  • Gas Used:实际消耗的 Gas 量。比如一笔简单的 ETH 转账固定消耗 21000 Gas。
  • Base Fee:基础费用,由网络拥堵程度决定,会被销毁(EIP-1559 引入)。
  • Priority Fee:小费,你给矿工/验证者的激励,越高越容易被优先打包。

为什么交易会失败?最常见的原因就是 Gas 不够。你设置的 gasLimit 太低,EVM 执行到一半发现 Gas 用完了,就会回滚所有状态变化,但已经消耗的 Gas 不会退还。嗯,这里要注意:失败的交易也要付手续费,因为计算资源确实被使用了。

我刚开始写合约时,经常在循环里踩坑。比如一个 for 循环,如果数组长度不可控,Gas 消耗就可能爆炸。你想想看,如果有人故意传一个超长的数组进来,你的合约可能直接耗尽 Gas 导致交易失败,甚至把调用者也拖垮。

我的建议:在合约里尽量避免无上限的循环。如果实在需要,可以用 require 限制最大迭代次数,或者改用“拉取模式”(Pull over Push)让用户自己分批处理。

2.4 钱包与私钥管理:你的命根子

私钥是什么?它就是你对以太坊账户的绝对控制权。谁掌握了私钥,谁就能动用该账户下的所有资产。所以私钥管理,是区块链开发者的基本功,也是最重要的安全防线。

常见的钱包类型:

  • 软件钱包:如 MetaMask、imToken。方便,但私钥存在本地,容易被木马或钓鱼攻击。
  • 硬件钱包:如 Ledger、Trezor。私钥存储在专用芯片里,交易需要物理确认。我个人强烈建议,但凡涉及主网资产,都用硬件钱包。
  • 纸钱包:把私钥或助记词写在纸上。离线存储,但容易丢失或损坏。

助记词(Mnemonic)是私钥的另一种表现形式。它由 12 或 24 个英文单词组成,通过 BIP39 协议可以推导出私钥。记住:助记词 = 私钥,泄露助记词等于交出所有资产。

我曾经犯过的错:有一次我把测试网的助记词截图发到了团队群里,想着反正是测试网没关系。结果那个助记词对应的地址,后来被我误用来部署了一个有真实价值的合约。虽然最后及时转移了资产,但这件事让我后怕了很久。从此以后,我养成了一个习惯:主网和测试网用完全不同的助记词,且永远不截图、不拍照、不复制到剪贴板。

关于私钥的存储,我给出几条铁律:

  1. 永远不要硬编码私钥。不要在代码里写死私钥,不要提交到 GitHub。用环境变量或者专门的密钥管理服务。
  2. 加密存储。如果必须存文件,用 AES 或类似算法加密,且密码要足够复杂。
  3. 多签和冷热分离。大额资金建议用多签钱包(如 Gnosis Safe),日常操作用热钱包,大额转账走冷钱包签名。
  4. 定期检查授权。你授权给 DeFi 协议的额度,如果不撤销,别人理论上可以一直动用你的资产。用 revoke.cash 这类工具定期清理不必要的授权。

好了,这一章的基础内容就这些。别看都是概念,但每一个都跟后面的智能合约开发息息相关。下一章我们就要开始动手写第一个合约了,到时候你会回来感谢这些基础的。