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…

    Web3與WASM 23小時前
    200
  • 引用類型詳解:數組、結構體、映射、字符串

    引用類型詳解:數組、結構體、映射、字符串 學習目標 掌握 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: …

    21小時前
    000
  • 繼承多態與庫合約

    繼承多態與庫合約 學習目標 掌握 Solidity 繼承機制與多態 理解 C3 線性化算法 掌握庫合約(library)的定義和使用 繼承基礎 繼承定義 使用 is 關鍵字 繼承的實現方式是代碼拷貝:部署後變成一個合約 可見性與繼承 private:子合約不可見,但不能定義同名成員 internal:子合約可見 public:完全可見 event 和 mod…

    Web3與WASM 17小時前
    000
簡體中文 繁體中文 English