W3
08智能合约中级10 个步骤4 个小节预计 60-90 分钟v1 · 更新于 2026-09-19

编写与发布智能合约:Solidity 实战

一条能真正跑通的合约开发路径:用零安装的 Remix IDE 起步,掌握 Solidity 版本声明、状态变量、函数可见性、view / pure、modifier 与 event,完整写一个带 owner 权限控制和事件的计数器合约,编译理解 ABI 与 Bytecode,切到 Sepolia 测试网领水龙头,用 MetaMask 注入部署,在浏览器上调用并验证源码,最后做 Gas 优化与安全自查,走完「写 → 编译 → 部署 → 调用 → 验证」全流程。

编写与发布智能合约:Solidity 实战
⚠️
本章要点提示

合约部署风险提示:本教程全程在 Sepolia 测试网 进行,测试 ETH 没有真实价值,请勿把主网私钥或助记词导入任何陌生工具,也绝不要把私钥、助记词写进代码或提交到 Git 仓库。合约一旦部署到主网即不可修改,且任何人可读可调用,上线前必须完成测试网验证、边界测试、Gas 评估与安全审计,并公开源码供社区审查。

小节 01

环境与语法准备

步骤 12
01

选择开发环境:Remix 起步,Hardhat / Foundry 进阶

登录记录进度

新手第一步用浏览器版 Remix IDE(remix.ethereum.org):零安装、打开即写,左侧文件树、中间编辑器、右侧插件面板(Compiler、Deploy & Run)都已内置,适合把整套流程先跑通。

等合约逻辑变复杂、需要写自动化测试与脚本部署时,再迁移到工程化工具:Hardhat(TypeScript/JavaScript 生态,插件丰富,脚本化部署体验好)或 Foundry(Rust 编写,用 Solidity 直接写测试,编译与测试速度更快)。

三者的编译产物与部署结果完全一致,区别只在开发体验。

选择开发环境:Remix 起步,Hardhat / Foundry 进阶
选择开发环境:Remix 起步,Hardhat / Foundry 进阶|界面示意 · remix.ethereum.org · 采集于 2026-09-18
🚫
避坑提醒:

只从官方域名进入开发工具,搜索引擎里的「Remix 中文版」「在线部署助手」多为仿冒站点,会窃取你后续连接的助记词与私钥。

💡
小技巧:

先不要纠结用哪套工具。用一个下午在 Remix 里完整走通「写、编译、部署、调用、验证」,比反复换工具更有价值。

Remix IDE 在线版
02

掌握 Solidity 基础语法骨架

登录记录进度

Solidity 文件顶部用 pragma solidity ^0.8.20; 声明编译器版本,^ 表示允许同主版本内的更高小版本,避免装错编译器导致语法报错。核心结构用 contract Counter { ... } 定义。

状态变量写在合约体内,如 uint256 private _count;,会永久占用存储槽。函数可见性有四档:public(内外都能调用)、private(仅本合约内部)、internal(本合约及子合约)、external(只能从外部调用,最省 Gas)。

不需要读写的函数标 view(读状态不写)、完全不读状态的标 puremodifier 用来写权限之类的复用校验,event 用于对外广播状态变化。

掌握 Solidity 基础语法骨架
掌握 Solidity 基础语法骨架|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
小节 02

写出并编译第一个合约

步骤 34
03

完整写一个带权限控制的计数器合约

登录记录进度

下面这份代码可以直接在 Remix 中编译运行,它包含状态变量、构造函数、事件、权限修饰符与三种典型函数:

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

contract Counter {
    uint256 private _count;
    address public owner;

    event CountChanged(address indexed operator, uint256 newValue);

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    constructor(uint256 initialValue) {
        owner = msg.sender;
        _count = initialValue;
    }

    function increment() external {
        _count += 1;
        emit CountChanged(msg.sender, _count);
    }

    function setNumber(uint256 newValue) external onlyOwner {
        _count = newValue;
        emit CountChanged(msg.sender, _count);
    }

    function count() external view returns (uint256) {
        return _count;
    }
}

要点:constructor 在部署时执行一次,把 msg.sender(部署者)记为 owner;onlyOwner 修饰器让 setNumber 只有 owner 能调用,未授权用户调用会因 require 失败而回滚;increment 对所有人开放;所有写操作都 emit 事件,方便链下服务索引。

完整写一个带权限控制的计数器合约
完整写一个带权限控制的计数器合约|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
🚫
避坑提醒:

权限校验是合约最容易被忽略的漏洞来源:任何会修改关键状态或转移资金的函数,都必须显式加权限判断,绝不能依赖「别人不知道这个函数」来保安全。

04

编译合约并理解 ABI 与 Bytecode

登录记录进度

在 Remix 左侧点击 Solidity Compiler 插件,编译器版本选择与 pragma 匹配的 0.8.20(可勾选 auto compile 自动编译),点击 Compile,绿色对勾表示通过。

编译产物有两样关键内容:ABI 是一段 JSON 数组,描述每个函数的名称、输入输出类型与是否可读状态,钱包和前端靠它拼出调用数据;Bytecode 是十六进制机器码,也就是部署时真正写进链上的那部分。

理解分工很重要:ABI 只影响「怎么调用」,会影响用户体验;Bytecode 才决定「合约到底做什么」,才是安全审计的对象。

编译合约并理解 ABI 与 Bytecode
编译合约并理解 ABI 与 Bytecode|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
💡
小技巧:

后期要在区块浏览器上验证源码时,需要用到与部署时完全一致的编译器版本和优化设置,建议一开始就把版本号记在项目 README 里。

小节 03

部署到测试网并调用

步骤 58
05

准备测试网账户与 Gas:切到 Sepolia 并领取测试币

登录记录进度

打开 MetaMask,点击顶部网络选择器切换到 Sepolia 测试网(若列表没有,在设置的高级选项里开启显示测试网络,或到 chainlist.org 一键添加)。测试网上的 ETH 没有真实价值,但部署与调用仍然需要它支付 Gas,因此要去水龙头(Faucet)领取:常用的有 Google Cloud Web3 Faucet、Alchemy Sepolia Faucet、Chainlink Faucet 等,通常要求钱包内有一定主网余额或完成登录验证,每次发放 0.1-0.5 Sepolia ETH,足够部署几十次简单合约。

准备测试网账户与 Gas:切到 Sepolia 并领取测试币
准备测试网账户与 Gas:切到 Sepolia 并领取测试币|界面示意 · sepoliafaucet.com · 采集于 2026-09-18
🚫
避坑提醒:

务必确认当前网络是 Sepolia 而不是 Ethereum Mainnet:在真实主网部署一次普通合约通常要花费几美元到几十美元 Gas,且部署后无法撤销。

💡
小技巧:

水龙头一般按地址和 IP 限频,24 小时内通常只能领一次,建议提前一天领好,避免部署时手忙脚乱。

06

部署到测试网:用 Injected Provider 注入 MetaMask

登录记录进度

回到 Remix 的 Deploy & Run Transactions 插件:Environment 选择 Injected Provider - MetaMask,此时 Remix 会请求连接钱包,页面顶部显示当前账户地址与 Sepolia 余额。

在 Deploy 输入框填入构造函数参数 initialValue(例如 0),点击 Deploy 后 MetaMask 弹出交易确认窗,核对网络是 Sepolia、Gas 费用合理,点击 Confirm。

等待几秒到几十秒交易上链,Remix 下方的 Deployed Contracts 区域会展开新合约,最上方就是合约地址,点击右侧复制按钮保存下来。

部署到测试网:用 Injected Provider 注入 MetaMask
部署到测试网:用 Injected Provider 注入 MetaMask|界面示意 · hardhat.org · 采集于 2026-09-18
🚫
避坑提醒:

部署交易确认前一定要核对 MetaMask 弹窗里的网络与合约来源,恶意网站可以伪造一个「部署」请求,实际却是把资产授权或转账给它控制的地址。

07

调用合约:读免费、写要付 Gas

登录记录进度

部署完成后在 Deployed Contracts 里展开合约:蓝色按钮代表只读函数,橙色按钮代表会写状态的函数。点击蓝色的 count,结果立刻返回,不弹钱包、不消耗 Gas,因为它只是本地节点对当前状态做一次查询。

点击橙色的 increment,MetaMask 会弹出交易确认,确认并等待上链后再点 count,数值加一——这一步真正写入了区块链状态,因此必须支付 Gas。再切到另一个钱包地址调用 setNumber,会因 onlyOwner 校验失败而报错回滚,这就是权限控制生效的样子。

调用合约:读免费、写要付 Gas
调用合约:读免费、写要付 Gas|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
🚫
避坑提醒:

合约执行失败时交易依然会被打包,Gas 通常照扣不退。请在本地或测试网充分试错,不要在主网上用真金白银调试。

💡
小技巧:

调试时先把所有只读函数点一遍,确认初始状态符合预期,再执行写操作,能省下不少因参数写错而浪费的 Gas。

08

在区块浏览器验证源码(Verify Contract)

登录记录进度

复制合约地址,打开 Sepolia Etherscan(sepolia.etherscan.io)搜索该地址,此时 Contract 标签页只有字节码、看不到源码。点击 Verify and Publish,选择编译器类型(Solidity 单文件)、版本 v0.8.20、License 选 MIT,粘贴源码,并在构造函数参数栏填入 ABI 编码后的参数。

提交后几十秒内验证完成,页面会显示绿色对勾的源码与可交互的 Read / Write Contract 面板。验证源码的意义是:任何人都能在浏览器上读代码、直接调用函数,项目的可信度与协作效率都会显著提升。

在区块浏览器验证源码(Verify Contract)
在区块浏览器验证源码(Verify Contract)|界面示意 · etherscan.io · 采集于 2026-09-18
🚫
避坑提醒:

源码开放验证只代表代码公开可读,不保证它没有漏洞或没有恶意逻辑。验证通过的合约同样可能包含后门函数,仍要看代码本身。

Sepolia Etherscan 区块浏览器
小节 04

优化、自查与动手清单

步骤 910
09

做 Gas 优化与安全自查

登录记录进度

Gas 优化围绕「少写存储、少传数据」展开:存储写入(SSTORE)是链上最昂贵的操作,能用事件替代记录的就别写进状态变量;函数参数优先用 calldata 而不是 memory,避免多余的内存拷贝;同一个变量多次自增时先累加再一次性写回;能用 uint256 就不折腾更小整数类型。安全方面,权限控制建议直接引入 OpenZeppelinOwnableOwnable2Step,而不是手写 owner 判断;所有对外转账函数都要考虑重入(Reentrancy),遵循「先改状态、后转账」的顺序或加 nonReentrant 修饰器;最后用 Remix 内置的静态分析插件扫一遍常见问题。

做 Gas 优化与安全自查
做 Gas 优化与安全自查|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
🚫
避坑提醒:

任何涉及资金转移的合约,上线主网前都应经过第三方审计,并通过「代码审查 + 测试网演练 + 小额灰度」三步验证,绝不能抱着试试看的心态直接上主网。

💡
小技巧:

OpenZeppelin 的合约库经过大量审计与实战检验,能直接复用就不要自己重写,自己写的每一行代码都是潜在风险点。

10

避开新手误区,走完完整动手清单

登录记录进度

常见误区有四个:直接把测试合约部署到主网,一部署就永久存在且可能被机器人扫描攻击;把私钥或助记词写进代码、.env 或提交到仓库,等于把钱直接交给全网;只测正常路径不做边界测试,例如重复调用、越权调用、传入 0 或极大值都不测;不做审计就上线,把所有用户资金押在自己刚学会的代码上。正确的动手清单是:在 Remix 里完整走一遍「写 → 编译 → 部署到 Sepolia → 调用 → 在 Etherscan 验证源码」,然后再用 Hardhat 或 Foundry 补上自动化测试与脚本化部署,形成可重复的工程流程。

避开新手误区,走完完整动手清单
避开新手误区,走完完整动手清单|界面示意 · docs.soliditylang.org · 采集于 2026-09-18
🚫
避坑提醒:

不要为了省钱跳过测试网,也不要让别人替你保管私钥。链上世界的规则是代码即法律、私钥即所有权,出错的代价由你自己承担。

💡
小技巧:

把「测试网先跑通一次」当成肌肉记忆。真正到了主网,你只有一次机会,而这个机会通常只需要几秒钟就会变成不可更改的事实。

来源与时效

本章记录平台 ethereum.org · 客户端 Web / App · 版本 v1 · 最后更新 2026-09-19 Web3 产品的界面与规则更新频繁,动手前请以官方当前界面与公告为准。

这一章可以动手试

区块链域有 2 个练习, 在浏览器里真跑(不连钱包、不发交易),可以拿它们验证刚读到的结论。

相关百科文章

看完本章后可以延伸阅读这些条目