跳到主要内容

以太坊与智能合约

以太坊是目前最流行的智能合约平台,它扩展了比特币的功能,允许开发者在区块链上部署任意代码。本章将深入介绍以太坊的技术架构和智能合约的工作原理。

以太坊概述

以太坊由 Vitalik Buterin 在 2013 年提出,2015 年正式上线。与比特币主要作为价值存储不同,以太坊被设计成一个可编程的区块链平台,支持智能合约和去中心化应用。

以太坊的特点

图灵完备:以太坊虚拟机(EVM)支持循环和复杂计算,理论上可以执行任意算法。这通过 Gas 机制防止无限循环。

账户模型:以太坊采用账户模型而非 UTXO 模型,更易于编程和理解。账户存储余额、代码和状态。

智能合约:开发者可以部署代码到区块链,代码自动执行且不可篡改。这为去中心化应用提供了基础。

快速出块:以太坊出块时间约 12-15 秒(PoS 后约 12 秒),比比特币的 10 分钟快得多。

以太坊的发展阶段

以太坊的发展分为四个主要阶段:

阶段名称时间主要更新
阶段 0信标链2020.12PoS 链上线
阶段 1合并2022.09PoW 转 PoS
阶段 2分片进行中提高扩展性
未来完整分片待定完整的分片链

以太坊架构

以太坊的架构可以分为多层,每层负责不同的功能。

网络层

网络层负责节点之间的通信。以太坊使用 DevP2P 协议进行节点发现和消息传输。主要功能包括:

  • 节点发现:通过 Kademlia DHT 发现对等节点
  • 区块同步:从其他节点下载区块和交易
  • 交易广播:将新交易传播到网络

共识层

共识层负责达成区块链状态的一致性。以太坊目前采用 PoS 共识机制。

信标链:信标链是 PoS 的核心,负责管理验证者、组织验证者委员会、处理最终确定性。

验证者:验证者需要质押 32 ETH,负责提议区块和验证区块。作恶会被罚没质押。

最终确定性:以太坊使用 Casper FFG 实现最终确定性。一旦区块被最终确定,就不可回滚。

执行层

执行层负责执行交易和维护状态。主要包括:

  • 交易执行:验证交易、执行 EVM 代码、更新状态
  • 状态管理:维护世界状态树
  • Gas 计算:计算交易消耗的资源

存储层

以太坊使用 Merkle Patricia Trie 存储数据:

  • 状态树:存储所有账户的状态
  • 存储树:存储合约的存储数据
  • 交易树:存储区块内的交易
  • 收据树:存储交易执行结果

以太坊虚拟机(EVM)

EVM 是以太坊的核心,它是一个沙盒环境,执行智能合约的字节码。

EVM 特点

沙盒隔离:每个合约在独立的沙盒中执行,无法直接访问其他合约的存储或外部系统。

确定性执行:相同输入必然产生相同输出,保证所有节点执行结果一致。

资源限制:通过 Gas 限制计算资源,防止无限循环。

栈式架构:EVM 是基于栈的虚拟机,操作数从栈中获取,结果压入栈中。

EVM 数据结构

:1024 个 256 位字的栈空间,用于存储操作数和中间结果。

内存:临时存储空间,交易执行完毕后清除。按 256 位字寻址,使用时支付 Gas。

存储:持久化存储空间,合约状态存储在这里。256 位到 256 位的键值对映射。

EVM 操作码

EVM 定义了约 150 个操作码,分为以下几类:

类别示例操作码说明
算术运算ADD, SUB, MUL, DIV基本数学运算
比较运算LT, GT, EQ比较操作
位运算AND, OR, XOR, NOT逻辑运算
栈操作PUSH, POP, DUP, SWAP栈管理
内存操作MLOAD, MSTORE内存读写
存储操作SLOAD, SSTORE持久化存储
控制流JUMP, JUMPI跳转指令
区块信息BLOCKHASH, TIMESTAMP获取区块信息
系统操作CREATE, CALL, SELFDESTRUCT合约交互

EVM 执行流程

  1. 从字节码中读取下一个操作码
  2. 根据操作码获取操作数(从栈中弹出)
  3. 执行操作
  4. 将结果压入栈
  5. 扣除相应 Gas
  6. 重复直到遇到 STOP 或 RETURN

智能合约

智能合约是存储在区块链上的程序代码,当满足预设条件时自动执行。

智能合约的特点

不可篡改:合约部署后代码无法修改,保证了协议的可预测性。

自动执行:当被调用时自动执行,无需人工干预。

透明公开:代码和状态对所有人可见,可以被审计。

可信计算:执行结果由共识机制保证,无需信任特定节点。

智能合约的生命周期

编写:使用 Solidity、Vyper 等语言编写合约代码。

编译:将源代码编译为 EVM 字节码和 ABI(应用二进制接口)。

部署:通过交易将字节码部署到区块链,获得合约地址。

调用:通过交易或调用执行合约函数。

销毁:合约可以包含自毁逻辑,销毁后代码和存储被清除。

合约调用方式

交易调用:会修改状态,需要支付 Gas,被矿工打包进区块。由外部账户发起。

// 发送交易调用合约
const tx = await contract.methods.setValue(42).send({
from: '0x...',
gas: 100000,
value: 0
});

静态调用:只读操作,不修改状态,不需要支付 Gas,本地执行。可以由合约或外部账户发起。

// 静态调用读取数据
const value = await contract.methods.getValue().call();

合约间调用

合约可以调用其他合约的函数,主要通过以下操作码:

CALL:调用另一个合约的函数,可以传递 ETH,修改被调用合约的状态。

DELEGATECALL:在调用者的上下文中执行被调用合约的代码,保持 msg.sender 和 msg.value 不变。常用于代理模式。

STATICCALL:保证调用不修改状态,用于视图函数。

以太坊代币标准

以太坊定义了多个代币标准,使得不同项目的代币可以互操作。

ERC-20:同质化代币

ERC-20 是最广泛使用的代币标准,定义了同质化代币的接口。

interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);

event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}

核心功能

  • 查询总供应量和账户余额
  • 代币转账
  • 授权第三方转账

ERC-721:非同质化代币

ERC-721 定义了非同质化代币(NFT)的标准,每个代币都是独一无二的。

interface IERC721 {
function balanceOf(address owner) external view returns (uint256);
function ownerOf(uint256 tokenId) external view returns (address);
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;

event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
}

特点

  • 每个 tokenId 唯一
  • 可以表示数字艺术品、收藏品等

ERC-1155:多代币标准

ERC-1155 允许一个合约管理多种代币类型,包括同质化和非同质化代币。

interface IERC1155 {
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

优势

  • 批量转账,节省 Gas
  • 单个合约管理多种代币
  • 适合游戏道具等场景

以太坊测试网

在主网部署前,开发者通常在测试网测试合约。主要的测试网:

测试网共识机制说明
SepoliaPoS最新的测试网,推荐使用
GoerliPoS即将弃用
HoleskyPoS新的质押测试网

获取测试 ETH 可以通过水龙头(Faucet)网站。

开发环境搭建

安装 Node.js

Web3 开发需要 Node.js 环境,建议使用 LTS 版本。

# 使用 nvm 安装 Node.js
nvm install --lts
nvm use --lts

安装 Hardhat

Hardhat 是最流行的以太坊开发框架。

# 创建项目目录
mkdir my-dapp && cd my-dapp

# 初始化项目
npm init -y

# 安装 Hardhat
npm install --save-dev hardhat

# 初始化 Hardhat 项目
npx hardhat init

项目结构

my-dapp/
├── contracts/ # 智能合约源码
├── scripts/ # 部署脚本
├── test/ # 测试文件
├── hardhat.config.js # Hardhat 配置
└── package.json

小结

本章介绍了以太坊平台的核心概念,包括 EVM、智能合约和代币标准。理解这些基础知识是开发去中心化应用的前提。下一章我们将深入学习 Solidity 编程语言,开始编写智能合约。

参考资料