Solidity中枚举转整数映射的实现及优化值递减操作问询
解决方案
问题的核心是Solidity不支持直接将字符串转换为枚举类型,你试图用animals._animal的方式访问枚举成员是行不通的——枚举成员是编译期常量,而字符串参数是运行时传入的,两者无法直接关联。以下是两种优化的实现方式:
方式1:使用字符串到枚举的映射
通过预定义字符串与枚举值的映射,将传入的字符串参数转换为对应的枚举后再操作计数映射:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Test { enum animals { CAT, DOG } mapping(animals => int8) public maps; mapping(string => animals) private _strToAnimal; constructor() { maps[animals.CAT] = 10; // 初始化字符串到枚举的映射关系 _strToAnimal["CAT"] = animals.CAT; _strToAnimal["DOG"] = animals.DOG; } function decrementAnimal(string calldata _animal) public { // 将字符串转换为枚举值 animals targetAnimal = _strToAnimal[_animal]; // 可选:校验输入的字符串是否对应有效枚举(防止传入无效字符串时默认操作CAT) require(targetAnimal == _strToAnimal[_animal], "Invalid animal type"); maps[targetAnimal] -= 1; } }
方式2:使用哈希对比转换字符串到枚举
如果枚举成员数量不多,可以通过字符串哈希对比的方式转换,这种方式不需要额外存储映射,更节省Gas:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Test { enum animals { CAT, DOG } mapping(animals => int8) public maps; constructor() { maps[animals.CAT] = 10; } // 内部函数:将字符串转换为枚举,无效输入直接回滚 function _strToAnimal(string calldata _animal) internal pure returns (animals) { bytes32 animalHash = keccak256(abi.encodePacked(_animal)); if (animalHash == keccak256(abi.encodePacked("CAT"))) { return animals.CAT; } else if (animalHash == keccak256(abi.encodePacked("DOG"))) { return animals.DOG; } revert("Invalid animal type"); } function decrementAnimal(string calldata _animal) public { animals targetAnimal = _strToAnimal(_animal); maps[targetAnimal] -= 1; } }
说明
- 两种方式都避免了为每个枚举成员单独编写递减函数的冗余代码
- 方式1的映射实现更直观,适合枚举成员较多的场景;方式2的哈希对比更节省链上存储,适合成员较少的场景
- 建议添加输入校验逻辑(如
require或revert),防止传入无效字符串时触发意外行为
内容的提问来源于stack exchange,提问作者Thibaut
相关产品推荐
相关产品推荐

