Solidity中如何实现可接收任意长度固定数组参数的工具函数
问题原因
Solidity中固定长度数组(类型形如T[N],N为编译期确定的数字)和动态长度数组(类型形如T[])是完全独立的两类数据类型,不存在隐式转换规则。你当前的写法等于要把string[2]、string[3]类型的存储引用强转成string[]类型的存储指针,所以会触发类型不匹配错误。
可行解决方案
方案1:使用泛型函数(推荐,适用于Solidity 0.8.0及以上版本)
Solidity 0.8版本开始支持编译期泛型参数,你可以把固定长度数组的长度作为泛型参数传入,工具函数可以适配任意长度的固定数组,不需要做数据拷贝,性能损耗为0。
修改后的代码示例:
contract test { string[2] internal list1 = ["str1", "str2"]; string[3] internal list2 = ["str3", "str4", "str5"]; function entryPoint() public view returns (uint256) { return utilityFunction(list1, list2); } // 泛型参数N、M分别对应两个传入固定数组的长度,编译期自动推导 function utilityFunction<uint256 N, uint256 M>(string[N] storage _list1, string[M] storage _list2) internal pure returns (uint256 result) { // 原有逻辑不需要修改,_list1.length、_list2.length可以正常获取对应长度 result = _list1.length + _list2.length; // 示例逻辑 } }
方案2:显式转换为动态数组(兼容旧版本Solidity)
如果你的项目使用的Solidity版本低于0.8.0不支持泛型,可以写辅助函数把固定长度数组的元素拷贝到动态数组中再传入。注意这种方法会产生数据拷贝,有一定gas成本,如果数组长度较大不推荐使用。
代码示例:
contract test { string[2] internal list1 = ["str1", "str2"]; string[3] internal list2 = ["str3", "str4", "str5"]; function entryPoint() public view returns (uint256) { string[] memory tempList1 = convertFixedToDynamic(list1); string[] memory tempList2 = convertFixedToDynamic(list2); return utilityFunction(tempList1, tempList2); } // 固定长度数组转动态数组的辅助函数,不同长度的数组需要对应写重载实现 function convertFixedToDynamic(string[2] memory arr) internal pure returns (string[] memory) { string[] memory res = new string[](2); for(uint i = 0; i < 2; i++) { res[i] = arr[i]; } return res; } function convertFixedToDynamic(string[3] memory arr) internal pure returns (string[] memory) { string[] memory res = new string[](3); for(uint i = 0; i < 3; i++) { res[i] = arr[i]; } return res; } function utilityFunction(string[] memory _list1, string[] memory _list2) internal pure returns (uint256 result) { // 原有逻辑 result = _list1.length + _list2.length; } }
内容的提问来源于stack exchange,提问作者Roman Lubushkin
相关产品推荐
相关产品推荐

