【区块链安全 | 第十三篇】Solidity 合约结构

文章目录

Solidity 合约

Solidity 中的合约类似于面向对象语言中的类。每个合约可以包含状态变量、函数、函数修饰符、事件、错误、结构体类型和枚举类型。此外,合约可以继承自其他合约。

还有一些特殊类型的合约,称为库(libraries)和接口(interfaces)。

Solidity 合约结构

本文针对合约结构提供一个快速概览。

状态变量

状态变量是那些值被永久存储在合约存储中的变量,或者是临时存储在瞬态存储中的变量,后者在每次交易结束时会被清除。

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract SimpleStorage {
    uint storedData; // 状态变量
    // ...
}

函数

函数是代码的可执行单元。函数通常定义在合约内,但也可以在合约外部定义。

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.1 <0.9.0;

contract SimpleAuction {
    function bid() public payable { // 函数
        // ...
    }
}

// 在合约外部定义的辅助函数
function helper(uint x) pure returns (uint) {
    return x * 2;
}

函数调用可以是内部的或外部的,并且具有不同的可见性级别。函数接受参数并返回变量,以便在它们之间传递数据和值。

函数修饰符

函数修饰符可用于以声明方式修改函数的语义。

特点

1.不支持重载,即不能使用相同名称但不同参数的修饰符。

2.与函数类似,修饰符可以被重写。

以下示例展示了 onlySeller 修饰符,该修饰符用于确保只有 seller(卖家)才能调用特定函数:

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;

contract Purchase {
    address public seller;

    modifier onlySeller() { // 定义修饰符
        require(
            msg.sender == seller,
            "Only seller can call this."
        );
        _; // 继续执行被修饰的函数
    }

    function abort() public view onlySeller { // 使用修饰符
        // 仅限卖家调用
    }
}

事件

Solidity 事件(Events)是 EVM(以太坊虚拟机)提供的日志机制,用于在链上记录特定操作,并供外部应用监听和使用。

特点

1.相比状态变量存储,事件日志存储在交易日志中,成本更低。

2.便于外部访问,前端应用(如 dApps)可以监听事件,实时获取区块链上的重要信息。

3.不可被合约内部读取,合约代码无法直接访问已触发的事件信息(但可由外部应用监听)。

以下示例展示了 HighestBidIncreased 事件,该事件在 bid() 函数被调用时触发,并记录投标人和投标金额。

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.22;

event HighestBidIncreased(address bidder, uint amount); // 事件

contract SimpleAuction {
    function bid() public payable {
        // ...
        emit HighestBidIncreased(msg.sender, msg.value); // 触发事件
    }
}

错误(Errors)

错误(Errors)允许为失败情况定义描述性名称和数据,通常通过 revert 语句实现。

特点

1.与直接使用字符串描述相比,错误的 gas 成本更低,并且可以编码额外数据。

2.可以使用 NatSpec 为用户提供错误的详细说明。

示例代码如下:

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;

/// 转账资金不足。请求金额为 `requested`,但仅有 `available` 可用。
error NotEnoughFunds(uint requested, uint available);

contract Token {
    mapping(address => uint) balances;

    function transfer(address to, uint amount) public {
        uint balance = balances[msg.sender];
        if (balance < amount)
            revert NotEnoughFunds(amount, balance); // 触发错误
        balances[msg.sender] -= amount;
        balances[to] += amount;
        // ...
    }
}

结构体类型(Struct Types)

结构体(Structs)是自定义类型,可用于将多个变量组合在一起。

示例代码如下:

solidity 复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract Ballot {
    // 定义一个名为 Voter(投票者)的结构体
    struct Voter { 
        uint weight;      // 该投票者的投票权重
        bool voted;       // 该投票者是否已经投票
        address delegate; // 该投票者委托的代理人地址
        uint vote;        // 该投票者所投的候选人编号
    }
}

枚举类型(Enum Types)

枚举(Enums)可用于创建一组预定义的 常量值,使代码更具可读性和可维护性。

特点:

1.用易理解的单词替代数字或布尔值,例如 State.Created 比 0 更直观。

2.枚举类型的变量只能取其定义的值,有助于减少错误。

3.Solidity 中的枚举本质上是 uint 类型,第一个成员默认值为 0,第二个成员 1,依此类推。

示例代码如下:

复制代码
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;

contract Purchase {
    // 定义一个枚举类型 State,表示合约的不同状态
    enum State { Created, Locked, Inactive }

    // 声明一个状态变量,默认值为 `State.Created`
    State public currentState;

    // 修改合约状态的方法
    function setLocked() public {
        currentState = State.Locked;
    }

    function setInactive() public {
        currentState = State.Inactive;
    }
}
相关推荐
Web极客码7 小时前
如何轻松、安全地管理密码(新手指南)
计算机网络·安全·web安全·网络安全
安全系统学习7 小时前
【网络安全】Qt免杀样本分析
java·网络·安全·web安全·系统安全
Bruce_Liuxiaowei8 小时前
文件上传漏洞深度解析:检测与绕过技术矩阵
安全·矩阵·文件上传漏洞
CYRUS STUDIO9 小时前
FART 脱壳某大厂 App + CodeItem 修复 dex + 反编译还原源码
android·安全·逆向·app加固·fart·脱壳
科技快报10 小时前
微算法科技(NASDAQ:MLGO)基于信任的集成共识和灰狼优化(GWO)算法,搭建高信任水平的区块链网络
科技·区块链
SilentCodeY10 小时前
Ubuntu 系统通过防火墙管控 Docker 容器
linux·安全·ubuntu·系统防火墙
海天胜景12 小时前
Delphi SetFileSecurity 设置安全描述符
安全
阿部多瑞 ABU12 小时前
# 从底层架构到应用实践:为何部分大模型在越狱攻击下失守?
gpt·安全·ai·自然语言处理
KKKlucifer12 小时前
从边界防护到内生安全:企业网络安全进化路线图
安全·web安全
Kjjia12 小时前
将内容明文存储在indexDB后,被指着鼻子骂道赶紧把数据隐藏...
前端·安全