← 返回
Web3与WASM 2026.03.09

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 開發框架

框架語言特點
HardhatJavaScript/TypeScript當前主流,插件生態豐富,內置 Hardhat Network
TruffleJavaScript老牌框架,社區成熟,逐漸被 Hardhat 取代
FoundrySolidity用 Solidity 寫測試,編譯速度極快

4.4 SDK(前端交互庫)

特點
ethers.js輕量、模塊化,當前推薦首選
web3.js老牌庫,API 豐富,社區龐大
viemTypeScript 優先,性能優異,新興選擇

五、第一個合約: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.0ABIEncoderV2 成爲默認編碼器
0.5.0函數可見性必須顯式聲明(不再有默認的 public)
0.6.0fallbackreceive 替代匿名回退函數

特別注意 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 篇。