第3章:智能合约入门:Solidity语言概览、合约结构、第一个HelloWorld合约

好,我们正式开始写代码了。

前面两章聊了Web3的宏观图景和开发环境搭建。现在,是时候亲手触碰智能合约了。我个人觉得,学任何语言,第一个程序都应该是「Hello World」。这不仅是仪式感,更是让你快速感知「这东西到底怎么跑起来」的最短路径。

3.1 Solidity:以太坊上的「官方语言」

Solidity,说白了就是专门给以太坊写智能合约用的。它长得有点像JavaScript,但骨子里完全不一样。你想想看,JS跑在浏览器里,而Solidity跑在区块链上——这就决定了它必须「一次部署,永不修改」。

我在项目中遇到过不少新手,上来就用JS的思维写Solidity,结果踩了一堆坑。比如循环里改状态变量,这在Solidity里可是要命的操作——gas费高得离谱。

核心要点:Solidity是静态类型语言,编译后生成EVM(以太坊虚拟机)字节码。它不支持浮点数,也没有标准库里的「随机数」——因为区块链是确定性的。

3.2 合约结构:一个智能合约长什么样?

一个标准的Solidity合约,通常包含这几部分。我习惯按这个顺序写,清晰又不容易漏东西。

组成部分 说明 我的经验
SPDX许可证标识 声明代码的开源许可 不写的话,编译会警告。我一般用MIT
Pragma指令 指定Solidity编译器版本 千万别写^0.8.0这种太宽泛的版本
Import语句 引入其他合约或库 尽量少用,减少依赖
合约声明 contract关键字 + 合约名 合约名首字母大写,这是行业惯例
状态变量 存储在链上的数据 注意可见性:public/private/internal
构造函数 部署时执行一次 可以用来初始化owner等
函数 合约的行为逻辑 记得加访问修饰符
事件 链上日志,供前端监听 能省gas就省,但调试时很有用
修饰器 函数执行前的检查 我最常用的是onlyOwner

小技巧:写合约时,我习惯先把结构骨架搭好,再往里填逻辑。就像写作文先列提纲一样,不容易跑偏。

3.3 第一个HelloWorld合约

好了,直接上代码。这是你能写出来的第一个真正意义上的智能合约。

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

contract HelloWorld {
    // 状态变量:存储在链上
    string public greeting;

    // 构造函数:部署时执行一次
    constructor() {
        greeting = "Hello, Web3!";
    }

    // 读取函数:不消耗gas(view关键字)
    function getGreeting() public view returns (string memory) {
        return greeting;
    }

    // 写入函数:消耗gas,改变链上状态
    function setGreeting(string memory _newGreeting) public {
        greeting = _newGreeting;
    }
}

嗯,这里要注意几个点。

第一,string public greeting 这行。加了 public 关键字后,Solidity会自动生成一个同名的getter函数。也就是说,你不用自己写 getGreeting() 也能读到 greeting 的值。但我还是习惯显式写出来,方便加注释。

第二,view 关键字。它告诉编译器:这个函数只读不写。调用它不需要花gas。我曾经见过有人把 view 函数写成普通函数,结果每次调用都扣gas,白白浪费钱。

第三,memory 关键字。在Solidity里,string 是引用类型,必须指定数据位置。函数参数和返回值用 memory,状态变量自动用 storage。这个规则我刚开始也搞混过,后来记住一句话:「参数用memory,变量用storage」

避坑指南:我曾经在写setGreeting函数时,忘了加 public 修饰符。结果部署后,前端死活调不到这个函数。排查了半天才发现——Solidity默认函数可见性是 internal,外部根本调不了。所以,写函数时第一件事就是确认可见性。

3.4 部署与交互:让合约真正跑起来

写完了合约,怎么验证它能不能跑?我建议用Remix IDE,在线就能编译部署,不用搭本地环境。

  1. 打开 remix.ethereum.org(别担心,这是个在线IDE)
  2. 新建文件,命名为 HelloWorld.sol
  3. 把上面的代码粘贴进去
  4. 点击「Solidity Compiler」选项卡,编译
  5. 切换到「Deploy & Run Transactions」选项卡
  6. 环境选「Remix VM」(模拟器,不花真钱)
  7. 点击「Deploy」按钮
  8. 在下方「Deployed Contracts」里找到你的合约
  9. 点击 greetinggetGreeting() 查看结果
  10. setGreeting 输入框里填个新字符串,点击调用
  11. 再查一次 greeting,看看变了没

你想想看,整个过程不到两分钟。但背后发生了什么?

  • Solidity代码被编译成了EVM字节码
  • 字节码被部署到虚拟机的区块链上
  • 你调用函数时,实际上是在向区块链发送交易
  • 交易被矿工打包,状态变量被永久存储

关键认知:一旦部署,合约代码就不可更改。但状态变量可以改——这就是「不可变逻辑,可变数据」的核心思想。我刚开始做项目时,总想着「先部署再改bug」,结果发现合约改不了,只能重新部署一个新地址。所以,测试一定要充分。

3.5 从HelloWorld到真实项目

这个HelloWorld合约虽然简单,但它包含了智能合约的所有核心要素:状态存储、读写函数、可见性控制、gas消耗机制。

我个人建议,你可以在这个基础上做几个小实验:

  • 加一个计数器,每次调用加1
  • 加一个owner地址,只有owner能修改greeting
  • 加一个事件,每次修改时触发

这些练习做完,你对Solidity的基本语法和合约结构就有感觉了。下一章,我们会深入讲数据类型和变量——嗯,那才是真正开始「玩」Solidity的时候。

课后作业:把上面的HelloWorld合约部署到Remix VM上,然后尝试调用setGreeting改成你自己的名字。再查一下greeting,看看是不是变了。如果没变,检查一下是不是忘了点「Transact」按钮——我当年就犯过这个低级错误。