3、Solidity语言入门:Solidity简介、开发环境(Remix IDE)、第一个智能合约(Hello World)、合约结构

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

前面两章聊了NFT是什么、ERC-721标准怎么来的,算是热身。从这一章开始,我们要真正动手了。你想想看,一个智能合约工程师,最趁手的兵器是什么?就是Solidity这门语言。

3.1 Solidity 到底是什么?

Solidity,说白了就是用来写以太坊智能合约的一门高级语言。它长得有点像JavaScript,也带点C++的影子。我刚开始学的时候,第一反应是:“这不就是JS加了个类型系统吗?” 嗯,后来发现事情没那么简单。

它有几个关键特点,我挑重要的说:

  • 面向合约:不是面向对象,是面向合约。每个合约就像一个独立的“小程序”,部署到链上后就永远跑在那里。
  • 静态类型:变量类型在编译时就定死了。你不能像JS那样随便把数字赋给字符串变量——编译器会直接报错。
  • 图灵完备:理论上你能用Solidity写出任何逻辑。但Gas限制会教你做人,哈哈。
  • 编译部署:写好的代码不能直接跑,得先编译成EVM(以太坊虚拟机)能理解的字节码,然后部署上链。
💡 我的小建议: 如果你之前写过JavaScript,学Solidity会很快上手。但千万别把JS的习惯带进来——比如随意改变变量类型、忽略Gas消耗,这些在Solidity里都是大忌。

3.2 开发环境:Remix IDE

工欲善其事,必先利其器。我推荐新手直接用Remix IDE。这是一个在线的Solidity开发环境,打开浏览器就能用,不需要装任何东西。

地址是:https://remix.ethereum.org/(放心,我不会让你点链接,自己搜一下就行)。

Remix 的界面分三块:

  • 左侧文件区:管理你的.sol文件。默认会有一个 contracts 文件夹,里面有几个示例合约。
  • 中间编辑区:写代码的地方。支持语法高亮、自动补全,挺方便的。
  • 右侧功能区:编译、部署、调试都在这里。有个“编译”按钮,点一下就能看到有没有语法错误。

我记得第一次用Remix时,最让我惊讶的是它内置了一个虚拟的以太坊环境。你不需要真的花钱买ETH,就能在浏览器里模拟部署和调用合约。这对学习来说太友好了。

⚠️ 注意: Remix 默认用的是 JavaScript 虚拟机(VM)环境。这个环境每次刷新页面都会重置,所有数据都会丢失。所以别把重要合约放在这里测试——我吃过这个亏,写了一个下午的测试数据,一个F5全没了。

3.3 第一个智能合约:Hello World

好了,咱们来写第一个合约。按照程序员的传统,先来个 Hello World。

在 Remix 里新建一个文件,命名为 HelloWorld.sol,然后输入以下代码:

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

contract HelloWorld {
    string public greeting = "Hello, NFT World!";

    function sayHello() public view returns (string memory) {
        return greeting;
    }

    function setGreeting(string memory _newGreeting) public {
        greeting = _newGreeting;
    }
}

来,一行一行拆开看:

  • // SPDX-License-Identifier: MIT —— 这是开源许可证声明。Solidity 编译器要求你必须写这个,不然会警告。我一般用 MIT,简单粗暴。
  • pragma solidity ^0.8.0; —— 声明编译器版本。^0.8.0 表示兼容 0.8.x 的所有小版本。为什么要有这个?因为不同版本的 Solidity 语法可能有差异,防止你的代码被错误的编译器编译。
  • contract HelloWorld { ... } —— 定义一个合约。合约名首字母大写,这是惯例。
  • string public greeting —— 声明一个公开的状态变量。public 关键字会自动生成一个同名的 getter 函数,方便外部读取。
  • function sayHello() public view returns (string memory) —— 一个只读函数。view 表示这个函数不会修改链上状态,所以调用它不需要花 Gas。
  • function setGreeting(...) public —— 一个写入函数。它会修改 greeting 的值,所以调用它需要支付 Gas。
🔑 关键点: 在 Solidity 里,public 变量会自动生成 getter,但不会自动生成 setter。如果你想修改它,必须自己写函数。这是出于安全考虑——你想想看,如果所有变量都能随便改,那合约还有什么安全性可言?

3.4 合约结构:骨架与血肉

写了一个完整的合约,咱们来总结一下 Solidity 合约的基本结构。说白了,一个合约就像一栋房子,有固定的骨架,你往里面填内容就行。

一个标准的 Solidity 合约包含以下几个部分:

组成部分 说明 是否必须
SPDX 许可证 声明开源协议 强烈建议
Pragma 指令 指定编译器版本 必须
Import 语句 引入其他合约或库 按需
合约定义 contract 合约名 { ... } 必须
状态变量 存储在链上的数据 按需
函数 合约的行为逻辑 按需
修饰器 用于权限控制等 按需
事件 链上日志,用于外部监听 按需
错误定义 自定义错误信息 按需

我个人的习惯是,写合约时先搭骨架:

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

contract MyContract {
    // 1. 状态变量
    // 2. 事件
    // 3. 修饰器
    // 4. 构造函数
    // 5. 外部函数
    // 6. 内部函数
}

为什么要按这个顺序?因为 Solidity 的编译器对声明顺序没有强制要求,但团队协作时,统一的代码风格能减少很多不必要的沟通成本。我曾经在一个项目里看到有人把状态变量写在函数后面,找起来真的很痛苦。

💡 避坑指南: 状态变量的声明顺序会影响合约的存储布局。Solidity 会按照你声明的顺序,把变量依次存储在链上的存储槽中。如果你以后要升级合约,改变变量顺序可能会导致数据错乱。所以一开始就要规划好。

3.5 编译与部署:见证奇迹的时刻

代码写完了,怎么跑起来?在 Remix 里很简单:

  1. 点击右侧的“Solidity Compiler”标签(就是那个带“S”的图标)。
  2. 确保编译器版本和 pragma 声明的一致。比如你写了 ^0.8.0,就选 0.8.x 的版本。
  3. 点击“Compile HelloWorld.sol”。如果没报错,你会看到一个绿色的勾。
  4. 切换到“Deploy & Run Transactions”标签(那个以太坊图标)。
  5. 环境选“Remix VM (Shanghai)”,然后点击“Deploy”。
  6. 部署成功后,下面会出现你的合约实例。点开它,就能看到 greetingsayHello 按钮了。

点一下 greetingsayHello,你会看到返回 "Hello, NFT World!"。再试试 setGreeting,输入 "Hello, Solidity!",然后再次调用 greeting,你会发现值变了。

嗯,这就是智能合约的魔力。你刚刚在区块链上(虽然是模拟的)部署了一个永不停机的程序。

🎯 总结一下: 这一章我们学了 Solidity 是什么、怎么用 Remix 开发、写了一个 Hello World 合约,还拆解了合约的基本结构。下一章我们会深入 Solidity 的数据类型和变量,那才是真正开始写复杂逻辑的地方。

记住,写智能合约和写普通程序最大的区别是:代码一旦上链,就几乎无法修改。所以,每写一行代码,都要问自己:“这个逻辑真的对吗?有没有漏洞?” 我见过太多因为少写一个检查而导致资产被盗的案例了。

好,今天就到这里。去 Remix 里敲一敲代码,感受一下。下一章见。