链链上图谱Web3 Knowledge Atlas↗
链上图谱/开发技术路线/Solidity 入门

Solidity / Tutorial 01

先写一个能解释清楚的合约。

从最小状态开始,理解 Solidity 如何保存数据、限制权限、发出事件,并把每个假设变成测试。

01 / Mental model

把合约看成状态机

合约不是运行在服务器上的普通 API。它部署在链上,有持久化状态;用户或其他合约通过交易调用函数,节点执行代码并把状态变化写入链上。

状态变量保存在链上的数据,读取通常不需要发送交易。
函数描述允许发生的状态变化和调用条件。
事件把重要变化记录为日志,供前端和索引器读取。

02 / First contract

一个最小的可读合约

下面的示例保存一个数字,只有拥有者可以更新,并在更新时发出事件。重点不是复制代码,而是观察状态、权限和日志之间的关系。

contract Counter {
    address public owner;
    uint256 public value;

    event ValueChanged(address indexed caller, uint256 value);

    constructor() {
        owner = msg.sender;
    }

    function set(uint256 nextValue) external {
        require(msg.sender == owner, "not owner");
        value = nextValue;
        emit ValueChanged(msg.sender, nextValue);
    }
}
读代码时先问:谁能调用?哪些状态会变化?外部调用在哪里?失败时状态是否已经更新?

03 / Access control

权限不是注释,是代码路径。

合约中的管理员、升级者、暂停者和资金提取者都应有明确的权限边界。不要只看函数名字中的 admin 或 safe,要沿着修饰器、继承和内部调用确认真实控制者。

检查点要确认的问题
初始化部署时 owner、管理员和关键地址由谁设置?是否可能被零地址或错误地址初始化?
升级谁能升级实现合约?升级是否需要多签或时间锁?
外部调用调用未知合约后,当前状态和重入防护是否正确?
紧急开关暂停功能能暂停哪些路径?恢复权限由谁掌握?

04 / Test first

把假设写成测试

至少测试成功路径、权限拒绝、边界输入和重复调用。涉及资金时,再测试余额守恒、失败回滚、授权范围和时间/价格变化。

01Arrange准备账户、初始状态和输入。
02Act执行一次调用或交易。
03Assert检查状态、事件和余额。
04Fuzz用多组边界输入验证不变量。

05 / Boundary

部署前的安全底线

教程代码没有经过审计,也没有覆盖真实协议的全部复杂性。部署前需要锁定编译器版本、运行单元和集成测试、检查依赖与权限,并在测试网或本地 fork 中验证完整资金路径。

不要做:把教程代码直接部署到真实资产环境;把私钥写进仓库、前端或脚本;把管理员权限交给未经核验的地址。

返回开发技术路线 → 阅读安全案例库 →