Solidity 入门与开发环境

Solidity 入门与开发环境

学习目标

  • 理解智能合约的本质与核心特性
  • 掌握合约在以太坊上的运行原理(Transaction + EVM)
  • 认识 Solidity 语言特点与开发工具链
  • 编写并部署第一个智能合约

前置知识

  • 了解区块链基本概念(区块、交易、共识)
  • 了解以太坊账户模型(EOA 与合约账户)
  • 基本编程经验(任意语言均可)

一、智能合约的根本性质

1.1 本质是契约(合同)

智能合约的英文是 Smart Contract,重点在 Contract(合同/契约)。它不仅仅是一段程序,更是一种跨组织、跨个体的信任关系的数字化表达

传统合同依赖法律体系和中介机构来保障执行,而智能合约依赖区块链网络和代码逻辑来保障执行——Code is Law

1.2 开发流程:定约、修约、废约

智能合约的生命周期可以类比传统合同:

阶段 传统合同 智能合约
定约 起草、签署合同 编写、部署合约(deploy)
修约 签订补充协议 部署新版本合约(代理模式)
废约 终止合同 调用 selfdestruct 或停用逻辑

1.3 不可变性(Immutable)与开源

智能合约一旦部署到区块链上,其代码不可被修改——这就是不可变性。这意味着:

  • 部署前必须经过充分的测试和审计
  • 修改逻辑只能通过部署新合约或使用代理模式(Proxy Pattern)
  • 合约代码通常会在 Etherscan 等区块浏览器上开源验证,任何人都可以阅读和审计

1.4 DeFi 说明商业契约,DAO 说明社会契约

智能合约的应用场景完美印证了它的「契约」本质:

  • DeFi(去中心化金融):借贷、交易、保险等金融合约的数字化,体现的是商业契约关系。例如 Uniswap 的交易合约、Aave 的借贷合约。
  • DAO(去中心化自治组织):投票、治理、提案等组织规则的数字化,体现的是社会契约关系。例如 MakerDAO 的治理合约。

二、合约运行原理

2.1 节点的双重角色

以太坊网络中的每个节点承担两个核心职责:

  • 一侧处理交易(Transaction):接收、验证、广播交易
  • 一侧运行 EVM(以太坊虚拟机):执行合约代码,更新状态

2.2 顺序执行,无并发

这是理解智能合约的关键:

  • Block 顺序生成:区块按照固定的时间间隔依次产生
  • Transaction 顺序执行:一个区块内的交易按照固定顺序逐个执行
  • 没有并发访问:不存在多线程、不存在竞态条件(Race Condition)

这与传统后端开发截然不同——你不需要考虑锁、信号量等并发控制问题,但也意味着性能受限于链的吞吐量。

2.3 Transaction 触发 EVM 执行

合约的执行永远是由一笔 Transaction 触发的,理解 Transaction 的结构至关重要:

字段 说明
from 发起者地址(EOA 账户)
to 目标地址(合约地址,或为空表示部署新合约)
value 转账的 ETH 数量(单位 wei)
calldata 调用数据(函数选择器 + 参数编码)

Transaction 与 EVM 执行流程

关键理解:合约执行的背后是 Transaction 和 EVM。每次调用合约函数,本质上都是发送一笔交易,由 EVM 解析 calldata 并执行对应的函数逻辑。读取操作(view/pure 函数)不需要发送交易,可以在本地节点直接执行。


三、Solidity 语言介绍

Solidity 是以太坊智能合约的主流开发语言,具有以下特点:

  • 强类型:所有变量必须声明类型,编译时检查类型安全
  • 面向对象:支持合约继承、接口、抽象合约
  • 多重继承:一个合约可以同时继承多个父合约(采用 C3 线性化解决菱形继承问题)
  • 语法参照 C++:大括号语法、分号结尾,对有 C/C++/Java/JavaScript 经验的开发者友好
  • 专为 EVM 设计:编译为 EVM 字节码,运行在以太坊虚拟机上

四、开发环境与工具链

4.1 solc 编译器

solc 是 Solidity 的官方编译器,将 .sol 源文件编译为 EVM 字节码和 ABI(Application Binary Interface)。

# 安装(macOS)
brew install solidity

# 编译合约
solc --bin --abi MyContract.sol

4.2 Remix IDE

Remix 是最适合入门的智能合约开发工具:

  • 在线版:直接在浏览器中使用,无需安装
  • 桌面版:Remix Desktop,提供离线开发能力
  • 内置编译器、部署工具、调试器
  • 支持连接 MetaMask 部署到真实网络

推荐入门阶段使用 Remix,后续项目开发再迁移到框架。

4.3 开发框架

框架 语言 特点
Hardhat JavaScript/TypeScript 当前主流,插件生态丰富,内置 Hardhat Network
Truffle JavaScript 老牌框架,社区成熟,逐渐被 Hardhat 取代
Foundry Solidity 用 Solidity 写测试,编译速度极快

4.4 SDK(前端交互库)

特点
ethers.js 轻量、模块化,当前推荐首选
web3.js 老牌库,API 丰富,社区庞大
viem TypeScript 优先,性能优异,新兴选择

五、第一个合约:NumberStorage

下面编写一个最简单的智能合约,实现数字的存储和读取:

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract NumberStorage {
    uint public x;

    function setX(uint px) public {
        x = px;
    }

    function getX() public view returns(uint) {
        return x;
    }

    function add(uint a, uint b) private pure returns(uint) {
        return a + b;
    }
}

代码逐行解析

第 1 行:许可证声明

// SPDX-License-Identifier: MIT

SPDX(Software Package Data Exchange)许可证标识符,声明代码的开源协议。从 Solidity 0.6.8 起,编译器会对缺少此声明的文件发出警告。常用值包括 MITGPL-3.0UNLICENSED(不开源)。

第 2 行:版本声明

pragma solidity >=0.8.2 <0.9.0;

指定编译器版本范围。pragma 是编译器指令,告诉编译器只有在版本满足条件时才编译此文件。

第 4 行:合约定义

contract NumberStorage {

contract 关键字定义一个合约,类似面向对象语言中的 class

第 5 行:状态变量

uint public x;

uint 是无符号整型(等同于 uint256),public 自动生成一个同名的 getter 函数。状态变量存储在区块链上,是合约的持久化数据。

第 7-9 行:写入函数

function setX(uint px) public {
    x = px;
}

public 表示外部和内部都可以调用。修改状态变量需要发送交易(消耗 Gas)。

第 11-13 行:读取函数

function getX() public view returns(uint) {
    return x;
}

view 表示只读取状态,不修改。调用 view 函数不消耗 Gas(本地执行)。

第 15-17 行:纯计算函数

function add(uint a, uint b) private pure returns(uint) {
    return a + b;
}
  • private:仅合约内部可调用
  • pure:既不读取也不修改状态,纯粹的计算函数

六、源文件结构

一个 Solidity 源文件的标准结构:

// 1. 许可证声明
// SPDX-License-Identifier: MIT

// 2. 版本声明
pragma solidity ^0.8.0;

// 3. import 语句(如有)
import "./OtherContract.sol";

// 4. 合约定义
contract MyContract {
    // ...
}

七、版本问题

7.1 语义化版本号(Semantic Versioning)

Solidity 遵循语义化版本号:MAJOR.MINOR.PATCH

  • MAJOR:不兼容的重大变更
  • MINOR:向后兼容的功能新增
  • PATCH:向后兼容的问题修复

7.2 版本声明的写法

pragma solidity ^0.8.0;    // >=0.8.0 且 <0.9.0
pragma solidity >=0.8.2 <0.9.0;  // 精确范围
pragma solidity 0.8.20;   // 仅限指定版本

7.3 重要版本变化

版本 重要变化
0.8.0 整型溢出默认抛出异常(不再需要 SafeMath)
0.8.0 ABIEncoderV2 成为默认编码器
0.5.0 函数可见性必须显式声明(不再有默认的 public)
0.6.0 fallbackreceive 替代匿名回退函数

特别注意 0.8.0 的整型溢出变化:低于 0.8.0 的版本中,uint8(255) + 1 的结果是 0(取模运算),这是大量安全漏洞的根源。0.8.0 起默认会抛出异常,极大提升了安全性。


八、合约基本结构

一个完整的合约可能包含以下元素:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MyContract {
    // 1. 状态变量 - 永久存储在区块链上
    uint public count;
    address public owner;

    // 2. 事件 - 用于记录日志,前端可以监听
    event CountChanged(uint newCount);

    // 3. 修饰符 - 函数执行的前置条件检查
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    // 4. 构造函数 - 合约部署时执行一次
    constructor() {
        owner = msg.sender;
    }

    // 5. 函数 - 合约的行为逻辑
    function increment() public onlyOwner {
        count += 1;
        emit CountChanged(count);
    }
}
元素 说明
状态变量 合约的持久化数据,存储在链上
函数 合约的行为,可读取或修改状态
修饰符(modifier) 可复用的函数前置/后置检查逻辑
事件(event) 链上日志,便于前端监听和索引
构造函数(constructor) 部署时执行一次,用于初始化

小结

本节我们了解了智能合约的本质是数字化的契约关系,理解了 Transaction + EVM 的执行模型,认识了 Solidity 语言和开发工具链,并编写了第一个智能合约。下一节我们将深入学习 Solidity 的值类型系统。


本文为 Web3 区块链系列第 3 篇,共 12 篇。

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/7486

(0)
Walker的头像Walker
上一篇 5天前
下一篇 2025年11月25日 06:00

相关推荐

  • 存储位置与拷贝机制:storage、memory、calldata

    存储位置与拷贝机制:storage、memory、calldata 学习目标 理解 EVM 中三种数据存储位置的特点,以及引用类型在不同存储位置之间赋值时的拷贝规则。 前置知识 已学习值类型和引用类型(数组、结构体、映射、字符串)。 三种存储位置 storage —— 持久化存储 类似数据库,数据永久保存在区块链上 成员变量(状态变量)默认存储在 stora…

  • 引用类型详解:数组、结构体、映射、字符串

    引用类型详解:数组、结构体、映射、字符串 学习目标 掌握 Solidity 中四种引用类型(数组、结构体、映射、字符串/变长字节数组)的定义和使用方法。 前置知识 已学习值类型(整型、布尔、地址、定长字节数组等)。 数组(Array) storage 中的数组 Solidity 中数组分为两种: 静态数组 T[K]:长度固定,编译时确定 动态数组 T[]:长…

  • Solidity 值类型详解

    Solidity 值类型详解 学习目标 掌握 Solidity 的整型、布尔、地址、定长字节数组、枚举等值类型 理解 EVM 256 位机器架构对类型设计的影响 掌握类型转换规则(隐式 vs 显式) 了解溢出问题的历史与解决方案 理解 Solidity 中所有类型的默认值机制 一、整型(int / uint) 1.1 基本概念 Solidity 提供有符号整…

  • 合约交互与 ABI

    合约交互与 ABI 学习目标 掌握合约间调用方式、接口定义、ABI 数据结构、Web3.js 访问合约的方法。 合约间调用基础 EOA(外部账号)发起调用,可能触发合约间的调用链 调用者必须持有被调用合约的地址 方式一:同文件内直接调用 当两个合约在同一个文件中时,可以直接通过合约类型和地址进行调用: // SPDX-License-Identifier: …

    22小时前
    100
  • 继承多态与库合约

    继承多态与库合约 学习目标 掌握 Solidity 继承机制与多态 理解 C3 线性化算法 掌握库合约(library)的定义和使用 继承基础 继承定义 使用 is 关键字 继承的实现方式是代码拷贝:部署后变成一个合约 可见性与继承 private:子合约不可见,但不能定义同名成员 internal:子合约可见 public:完全可见 event 和 mod…

    Web3与WASM 18小时前
    100
简体中文 繁体中文 English