合约结构 #

一、合约组成 #

1.1 完整合约结构 #

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

contract CompleteContract {
    // 1. 状态变量
    uint256 public count;
    address public owner;
    
    // 2. 事件
    event CountChanged(uint256 newCount);
    
    // 3. 修饰器
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    // 4. 构造函数
    constructor() {
        owner = msg.sender;
    }
    
    // 5. 函数
    function increment() public {
        count++;
        emit CountChanged(count);
    }
    
    // 6. 接收函数
    receive() external payable {}
    
    // 7. 回退函数
    fallback() external payable {}
}

1.2 组成部分说明 #

组成部分 说明 示例
SPDX声明 许可证标识 // SPDX-License-Identifier: MIT
pragma 编译器版本 pragma solidity ^0.8.0;
import 导入文件 import "./Other.sol";
状态变量 永久存储 uint256 public count;
事件 日志记录 event Transfer(...);
修饰器 函数修饰 modifier onlyOwner() {...}
构造函数 初始化 constructor() {...}
函数 业务逻辑 function foo() {...}
接收函数 接收ETH receive() external payable {}
回退函数 未知调用 fallback() external payable {}

二、状态变量 #

2.1 状态变量声明 #

solidity
contract StateVariables {
    // 基本类型
    uint256 public count;
    int256 private balance;
    bool internal active;
    address public owner;
    
    // 复合类型
    string public name;
    bytes32 public hash;
    
    // 引用类型
    uint256[] public numbers;
    mapping(address => uint256) public balances;
    
    // 结构体
    struct User {
        address wallet;
        string name;
    }
    User public user;
    
    // 枚举
    enum Status { Pending, Active, Completed }
    Status public status;
}

2.2 可见性 #

solidity
contract StateVariableVisibility {
    // public:自动生成getter函数
    uint256 public publicVar;
    
    // private:仅本合约可访问
    uint256 private privateVar;
    
    // internal:本合约和子合约可访问
    uint256 internal internalVar;
    
    // 状态变量不能是external
    // uint256 external externalVar;  // 错误
}

2.3 常量与不可变 #

solidity
contract ConstantsAndImmutables {
    // constant:编译时确定,不占用storage
    uint256 public constant MAX_SUPPLY = 1000000;
    address public constant ZERO_ADDRESS = address(0);
    
    // immutable:部署时确定,不占用storage
    address public immutable owner;
    uint256 public immutable createdAt;
    
    constructor() {
        owner = msg.sender;
        createdAt = block.timestamp;
    }
    
    // constant和immutable的区别:
    // constant:编译时确定值
    // immutable:部署时确定值
}

三、函数 #

3.1 函数声明 #

solidity
contract FunctionDeclaration {
    // 基本函数
    function getValue() public pure returns (uint256) {
        return 1;
    }
    
    // 带参数函数
    function add(uint256 a, uint256 b) public pure returns (uint256) {
        return a + b;
    }
    
    // 多返回值
    function getMultiple() public pure returns (uint256, bool) {
        return (1, true);
    }
    
    // 命名返回值
    function getNamed() public pure returns (uint256 number, bool flag) {
        number = 1;
        flag = true;
    }
}

3.2 函数可见性 #

solidity
contract FunctionVisibility {
    // public:任何地方可调用
    function publicFunction() public pure returns (string memory) {
        return "public";
    }
    
    // private:仅本合约可调用
    function privateFunction() private pure returns (string memory) {
        return "private";
    }
    
    // internal:本合约和子合约可调用
    function internalFunction() internal pure returns (string memory) {
        return "internal";
    }
    
    // external:仅外部可调用
    function externalFunction() external pure returns (string memory) {
        return "external";
    }
}

四、事件 #

4.1 事件声明 #

solidity
contract EventDeclaration {
    // 基本事件
    event Transfer(address indexed from, address indexed to, uint256 value);
    
    // 带indexed参数
    event Deposit(address indexed user, uint256 amount);
    
    // 无indexed参数
    event StatusChanged(string newStatus);
    
    // 多个indexed参数(最多3个)
    event MultiIndexed(
        address indexed sender,
        address indexed recipient,
        uint256 indexed amount
    );
}

4.2 触发事件 #

solidity
contract EventEmission {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Deposit(address indexed user, uint256 amount);
    
    mapping(address => uint256) public balances;
    
    function transfer(address to, uint256 amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        
        balances[msg.sender] -= amount;
        balances[to] += amount;
        
        // 触发事件
        emit Transfer(msg.sender, to, amount);
    }
    
    function deposit() public payable {
        require(msg.value > 0, "Must send ETH");
        balances[msg.sender] += msg.value;
        
        // 触发事件
        emit Deposit(msg.sender, msg.value);
    }
}

4.3 indexed的作用 #

solidity
contract IndexedExample {
    // indexed参数可以被过滤查询
    event Transfer(
        address indexed from,   // 可过滤
        address indexed to,     // 可过滤
        uint256 value           // 不可过滤
    );
    
    // 查询示例(在Web3中):
    // contract.queryFilter(
    //     contract.filters.Transfer(fromAddress, null)
    // )
    // 可以快速找到所有从fromAddress发出的转账
}

五、修饰器 #

5.1 修饰器声明 #

solidity
contract ModifierDeclaration {
    address public owner;
    
    // 基本修饰器
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;  // 继续执行函数体
    }
    
    // 带参数的修饰器
    modifier minAmount(uint256 amount) {
        require(msg.value >= amount, "Insufficient ETH");
        _;
    }
    
    // 复杂修饰器
    modifier validAddress(address addr) {
        require(addr != address(0), "Invalid address");
        _;
    }
}

5.2 使用修饰器 #

solidity
contract ModifierUsage {
    address public owner;
    bool public paused;
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    modifier whenNotPaused() {
        require(!paused, "Contract paused");
        _;
    }
    
    modifier minAmount(uint256 amount) {
        require(msg.value >= amount, "Insufficient ETH");
        _;
    }
    
    constructor() {
        owner = msg.sender;
    }
    
    // 单个修饰器
    function setPaused(bool _paused) public onlyOwner {
        paused = _paused;
    }
    
    // 多个修饰器
    function sensitiveOperation() public onlyOwner whenNotPaused {
        // 敏感操作
    }
    
    // 带参数的修饰器
    function deposit() public payable minAmount(1 ether) {
        // 存款操作
    }
}

5.3 修饰器执行顺序 #

solidity
contract ModifierOrder {
    modifier mod1() {
        // 1. mod1开始
        _;
        // 4. mod1结束
    }
    
    modifier mod2() {
        // 2. mod2开始
        _;
        // 3. mod2结束
    }
    
    function test() public mod1 mod2 {
        // 3. 函数体
    }
    
    // 执行顺序:mod1开始 -> mod2开始 -> 函数体 -> mod2结束 -> mod1结束
}

六、结构体与枚举 #

6.1 结构体 #

solidity
contract StructExample {
    struct User {
        address wallet;
        string name;
        uint256 balance;
        bool verified;
    }
    
    User public owner;
    User[] public users;
    mapping(address => User) public userMap;
    
    function createUser(
        address _wallet,
        string memory _name,
        uint256 _balance
    ) public {
        User memory newUser = User({
            wallet: _wallet,
            name: _name,
            balance: _balance,
            verified: false
        });
        
        users.push(newUser);
        userMap[_wallet] = newUser;
    }
    
    function updateUser(address _wallet, string memory _name) public {
        User storage user = userMap[_wallet];
        user.name = _name;
    }
}

6.2 枚举 #

solidity
contract EnumExample {
    enum Status { Pending, Active, Completed, Cancelled }
    
    Status public status;
    
    function setStatus(Status _status) public {
        status = _status;
    }
    
    function getStatus() public view returns (Status) {
        return status;
    }
    
    function getStatusValue() public view returns (uint8) {
        return uint8(status);
    }
    
    function nextStatus() public {
        if (status == Status.Pending) {
            status = Status.Active;
        } else if (status == Status.Active) {
            status = Status.Completed;
        }
    }
}

七、综合示例 #

7.1 代币合约 #

solidity
contract Token {
    // 状态变量
    string public name;
    string public symbol;
    uint8 public decimals;
    uint256 public totalSupply;
    address public owner;
    
    // 映射
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    
    // 事件
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    // 修饰器
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    // 构造函数
    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals,
        uint256 _totalSupply
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
        totalSupply = _totalSupply;
        owner = msg.sender;
        
        balanceOf[msg.sender] = _totalSupply;
        emit Transfer(address(0), msg.sender, _totalSupply);
    }
    
    // 函数
    function transfer(address to, uint256 amount) public returns (bool) {
        require(to != address(0), "Invalid recipient");
        require(balanceOf[msg.sender] >= amount, "Insufficient balance");
        
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        
        emit Transfer(msg.sender, to, amount);
        return true;
    }
    
    function approve(address spender, uint256 amount) public returns (bool) {
        require(spender != address(0), "Invalid spender");
        
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }
    
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public returns (bool) {
        require(from != address(0), "Invalid from");
        require(to != address(0), "Invalid to");
        require(balanceOf[from] >= amount, "Insufficient balance");
        require(allowance[from][msg.sender] >= amount, "Insufficient allowance");
        
        balanceOf[from] -= amount;
        balanceOf[to] += amount;
        allowance[from][msg.sender] -= amount;
        
        emit Transfer(from, to, amount);
        return true;
    }
    
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Invalid new owner");
        
        address previousOwner = owner;
        owner = newOwner;
        
        emit OwnershipTransferred(previousOwner, newOwner);
    }
}

八、最佳实践 #

8.1 代码组织 #

solidity
contract CodeOrganization {
    // 1. 状态变量(按可见性分组)
    uint256 public publicVar;
    uint256 internal internalVar;
    uint256 private privateVar;
    
    // 2. 事件
    event ValueChanged(uint256 newValue);
    
    // 3. 修饰器
    modifier validValue(uint256 value) {
        require(value > 0, "Invalid value");
        _;
    }
    
    // 4. 构造函数
    constructor() {
        // 初始化
    }
    
    // 5. 接收函数
    receive() external payable {}
    
    // 6. 回退函数
    fallback() external payable {}
    
    // 7. external函数
    function externalFunction() external pure returns (uint256) {
        return 1;
    }
    
    // 8. public函数
    function publicFunction() public pure returns (uint256) {
        return 1;
    }
    
    // 9. internal函数
    function internalFunction() internal pure returns (uint256) {
        return 1;
    }
    
    // 10. private函数
    function privateFunction() private pure returns (uint256) {
        return 1;
    }
}

8.2 命名约定 #

solidity
contract NamingConventions {
    // 状态变量:小驼峰
    uint256 public totalSupply;
    address public owner;
    
    // 常量:全大写下划线分隔
    uint256 public constant MAX_SUPPLY = 1000000;
    
    // 私有变量:下划线前缀
    uint256 private _balance;
    
    // 事件:大驼峰
    event Transfer(address indexed from, address indexed to, uint256 value);
    
    // 修饰器:小驼峰,表达条件
    modifier onlyOwner() {
        _;
    }
    
    // 函数:小驼峰
    function transfer(address to, uint256 amount) public returns (bool) {
        return true;
    }
    
    // 内部函数:下划线前缀
    function _validateAddress(address addr) internal pure returns (bool) {
        return addr != address(0);
    }
}

九、总结 #

合约结构要点:

组成部分 说明 推荐位置
状态变量 永久存储 合约顶部
事件 日志记录 状态变量后
修饰器 函数修饰 事件后
构造函数 初始化 修饰器后
函数 业务逻辑 构造函数后

使用建议:

  • 按照推荐顺序组织代码
  • 使用有意义的命名
  • 添加必要的注释
  • 遵循代码规范

接下来,让我们学习状态变量!

最后更新:2026-03-27