【区块链安全 | 第十三篇】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;
    }
}
相关推荐
ALe要立志成为web糕手26 分钟前
用Python实现TCP代理
网络·python·网络协议·tcp/ip·安全·web安全
神经毒素1 小时前
WEB安全--文件上传漏洞--黑名单绕过
安全·web安全
FreeBuf_1 小时前
Ubuntu 安全限制遭突破:攻击者可利用内核漏洞提权
linux·安全·ubuntu
阳光普照世界和平1 小时前
您使用的开源软件许可证是否存在冲突呢?
安全
恒拓高科WorkPlus2 小时前
局域网视频软件BeeWorks Meet,企业内部安全会议不断线
网络·安全·音视频
AORO_BEIDOU4 小时前
卫星电话究竟是“锦上添花”?还是“刚需之选”?
科技·安全·智能手机·信息与通信
Doris Liu.9 小时前
如何检测代码注入(Part 2)
windows·python·安全·网络安全·网络攻击模型
秋说11 小时前
【区块链安全 | 第八篇】多签机制及恶意多签
安全·区块链
68岁扶墙肾透12 小时前
Java安全-FastJson反序列化分析
java·安全·web安全·网络安全·网络攻击模型·安全架构·fastjson
CryptoPP14 小时前
基于WebSocket的金融数据实时推送系统架构设计对接多国金融数据API
websocket·网络协议·金融·系统架构·区块链