枚举(Enum)是Solidity中用于创建用户定义类型的重要特性,可以定义一组命名常量,常用于状态机实现和代码可读性提升。本文详细介绍枚举的定义、使用方法和实际应用场景。

Solidity Enum


一、什么是枚举

一、1 基本概念

枚举(Enum)是一种用户定义的类型,用于创建一组命名常量。枚举值从0开始递增,每个值都有一个名称,使代码更加可读和易于维护。

二、2 枚举的特点

1
命名常量:
  • 使用有意义的名称
  • 提高代码可读性
  • 避免魔法数字
  • 类型安全
1
自动编号:
  • 从0开始递增
  • 可以显式转换为整数
  • 最多256个值
  • 节省存储空间
1
类型安全:
  • 编译时检查
  • 防止无效值
  • 减少错误
  • 提高可靠性

二、如何定义和使用枚举

三、1 基本定义

1
简单枚举:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pragma solidity ^0.8.0;

contract EnumExample {
enum Status { Pending, Approved, Rejected, Cancelled }

Status public currentStatus;

function setStatus(Status _status) public {
currentStatus = _status;
}

function getStatus() public view returns (Status) {
return currentStatus;
}

1
2
3
4
5
枚举值:
- `Status.Pending` = 0
- `Status.Approved` = 1
- `Status.Rejected` = 2
- `Status.Cancelled` = 3

四、2 枚举操作

1
2
3
设置枚举值:
function approve() public {
currentStatus = Status.Approved;

}

1
2
function reject() public {
currentStatus = Status.Rejected;

}
比较枚举:solidity

1
2
function isApproved() public view returns (bool) {
return currentStatus == Status.Approved;

}

1
2
function isPending() public view returns (bool) {
return currentStatus == Status.Pending;

}
类型转换:solidity

1
2
function getStatusValue() public view returns (uint8) {
return uint8(currentStatus); // 转换为整数

}

1
2
3
function setStatusByValue(uint8 _value) public {
require(_value <= uint8(Status.Cancelled), "Invalid status");
currentStatus = Status(_value); // 整数转枚举

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

### 五、3 枚举限制

值数量限制:
- 超过会编译错误
- 每个值占用1字节
- 存储效率高

默认值:
- 枚举默认值为第一个值
- `Status public status;` 默认为 `Status.Pending`
- 需要显式初始化

## 三、应用场景

### 六、1 状态机

订单状态:
contract Order {
enum OrderStatus { Created, Paid, Shipped, Delivered, Cancelled }

OrderStatus public status;
mapping(OrderStatus => bool) public allowedTransitions;

constructor() {
allowedTransitions[OrderStatus.Created] = true;
allowedTransitions[OrderStatus.Paid] = true;
}

function pay() public {
require(status == OrderStatus.Created, "Invalid status");
status = OrderStatus.Paid;
}

function ship() public {
require(status == OrderStatus.Paid, "Invalid status");
status = OrderStatus.Shipped;
}
`工作流管理:`solidity
contract Workflow {
enum Stage { Draft, Review, Approved, Published }

Stage public currentStage;

function nextStage() public {
if (currentStage == Stage.Draft) {
currentStage = Stage.Review;
} else if (currentStage == Stage.Review) {
currentStage = Stage.Approved;
} else if (currentStage == Stage.Approved) {
currentStage = Stage.Published;
}

七、2 权限管理

1
2
3
用户角色:
contract AccessControl {
enum Role { None, User, Moderator, Admin }
1
mapping(address => Role) public roles;
1
2
3
function setRole(address user, Role role) public {
require(roles[msg.sender] == Role.Admin, "Not admin");
roles[user] = role;
}
1
2
function hasPermission(address user, Role requiredRole) public view returns (bool) {
return uint8(roles[user]) >= uint8(requiredRole);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

### 八、3 投票系统

投票选项:
contract Voting {
enum VoteOption { Abstain, Yes, No }

mapping(address => VoteOption) public votes;
mapping(VoteOption => uint256) public voteCounts;

function vote(VoteOption option) public {
require(votes[msg.sender] == VoteOption.Abstain, "Already voted");
votes[msg.sender] = option;
voteCounts[option]++;
}

function getWinner() public view returns (VoteOption) {
if (voteCounts[VoteOption.Yes] > voteCounts[VoteOption.No]) {
return VoteOption.Yes;
} else if (voteCounts[VoteOption.No] > voteCounts[VoteOption.Yes]) {
return VoteOption.No;
} else {
return VoteOption.Abstain;
}

四、最佳实践

九、1 命名规范

1
2
3
清晰命名:
// 好的命名
enum OrderStatus { Pending, Processing, Completed, Cancelled }
1
2
// 避免模糊命名
enum State { S1, S2, S3, S4 } // 不推荐

使用前缀:solidity

1
enum ProposalStatus { ProposalPending, ProposalActive, ProposalSucceeded, ProposalFailed }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

### 十、2 状态转换

验证转换:
function transition(Status newStatus) public {
require(isValidTransition(currentStatus, newStatus), "Invalid transition");
currentStatus = newStatus;
}

function isValidTransition(Status from, Status to) internal pure returns (bool) {
if (from == Status.Pending && to == Status.Approved) return true;
if (from == Status.Pending && to == Status.Rejected) return true;
if (from == Status.Approved && to == Status.Cancelled) return true;
return false;
}

十一、3 Gas优化

1
2
3
使用枚举替代字符串:
// 不推荐:使用字符串
string public status = "pending";
1
2
3
// 推荐:使用枚举
enum Status { Pending, Approved }
Status public status;

存储效率:
- 枚举只占用1字节
- 比字符串节省Gas
- 比整数更语义化

## 五、总结

枚举是Solidity中提高代码可读性和类型安全的重要特性。关键要点:

定义使用:
- 定义命名常量集合
- 从0开始自动编号

应用场景:
- 状态机实现
- 权限管理
- 投票系统
- 工作流管理

最佳实践:
- 使用清晰命名
- 验证状态转换
- 替代字符串提高效率

通过合理使用枚举,可以编写更清晰、更安全、更高效的智能合约代码。

本文标题: Solidity枚举类型

发布时间: 2023年02月04日 00:00

最后更新: 2025年12月30日 08:54

原始链接: https://haoxiang.eu.org/9d790bb1/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码