Solidity 代码结构
Solidity 智能合约的代码具有清晰的结构化组织方式,下面我将详细介绍一个标准 Solidity 合约的完整结构及各部分的作用。
1、版本声明和许可标识
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
SPDX 许可证标识:指定合约的开源许可证类型(如 MIT、GPL 等)
pragma 版本指令:声明编译器版本要求
0.8.17: 严格使用0.8.17版本
^0.8.0:表示0.8.0及以上但不包括0.9.0
>=0.7.0 <0.9.0: 0.7.0到0.9.0之间(不包括0.9.0)
2、导入语句
// 相对路径导入
import "../utils/Helpers.sol";
// 绝对路径导入(取决于项目配置)
import "/project/contracts/Token.sol";
// 从 OpenZeppelin 合约导入
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// 从其他安装的包导入
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
// 从 URL 导入
import "
// 部分导入
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";用于引入其他合约文件或库
支持相对路径和通过 npm 安装的包(如 OpenZeppelin 合约、chainlink合约)
3. 合约主体结构
状态变量
contract MyContract {
// 公开状态变量(自动生成getter函数)
uint256 public count;
// 私有状态变量
address private owner;
// 常量
uint256 constant MAX_SUPPLY = 1000;
// 不可变变量(只能在构造函数赋值)
uint256 immutable creationTime;
}结构体和枚举
// 结构体定义
struct User {
string name;
uint256 balance;
bool isActive;
}
// 枚举类型
enum Status { Active, Inactive, Suspended }事件定义
event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value);
修饰符
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}构造函数
constructor(uint256 initialCount) {
count = initialCount;
owner = msg.sender;
creationTime = block.timestamp;
}函数定义
// 普通函数
function increment() public {
count += 1;
}
// 带修饰符的函数
function reset() public onlyOwner {
count = 0;
}
// view函数(只读)
function getCount() public view returns (uint256) {
return count;
}
// pure函数(不访问状态)
function add(uint256 a, uint256 b) public pure returns (uint256) {
return a + b;
}
// payable函数(可接收ETH)
function deposit() public payable {
// 处理逻辑
}4、完整合约示例
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
contract Counter is Ownable {
uint256 public count;
uint256 immutable maxCount;
event CountChanged(uint256 newCount);
constructor(uint256 _maxCount) {
maxCount = _maxCount;
}
modifier belowMax() {
require(count < maxCount, "Reached maximum");
_;
}
function increment() public belowMax {
count += 1;
emit CountChanged(count);
}
function reset() public onlyOwner {
count = 0;
emit CountChanged(0);
}
function getMax() public view returns (uint256) {
return maxCount;
}
}5、代码结构最佳实践
布局顺序:通常按照版本声明 → 导入 → 合约 → 状态变量 → 事件 → 修饰符 → 函数 的顺序组织
可见性:明确指定函数和变量的可见性(public/private/internal/external)
注释规范:使用 NatSpec 格式注释
模块化:将复杂逻辑拆分为多个合约或库
安全考虑:使用检查-效果-交互(CEI)模式