如何从已部署合约读取结构体数组?Solidity跨合约调用结构体类型不匹配问题求助
Solidity跨合约读取结构体数组:类型转换错误解决办法
你遇到的这个TypeError核心原因很明确:Solidity将不同作用域(比如接口和合约)中定义的同名结构体视为完全独立的类型,哪怕它们的字段完全一致。IContract1.UserInfo和Contract2.UserInfo在编译器眼里就是两个毫不相关的类型,自然无法直接隐式转换。
下面给你两种简单有效的解决方案:
方案1:复用接口中的结构体(推荐)
最直接的解决方式是不在Contract2中重复定义UserInfo结构体,直接使用接口IContract1里的版本。这样从根源上避免了类型不匹配的问题,代码修改后如下:
pragma solidity ^0.8.7; interface IContract1{ struct UserInfo{ uint id ; string ime; } // 注意:Contract1中arr是public状态变量,自动生成的getter是view函数,接口里要加上view修饰符 function arr(uint index) external view returns(UserInfo memory ); } contract Contract2{ // 移除本地的UserInfo定义,直接使用接口的类型 event UserEVENT (IContract1.UserInfo UserInfo); IContract1.UserInfo[] public newarr; function foo(address addr, uint i) external { IContract1.UserInfo memory fetchedUser = IContract1(addr).arr(i); emit UserEVENT(fetchedUser); newarr.push(fetchedUser); // 直接存入本地数组也没问题 } }
这里额外提醒一个细节:原接口中的arr函数没有加view修饰符,但Contract1里的arr是public状态变量,自动生成的getter函数是view类型的,所以接口里补上view更符合Solidity规范,还能避免不必要的gas消耗。
方案2:手动转换结构体类型
如果因为业务需求必须在Contract2中使用本地定义的UserInfo,那可以通过逐个字段赋值的方式手动完成类型转换:
pragma solidity ^0.8.7; interface IContract1{ struct UserInfo{ uint id ; string ime; } function arr(uint index) external view returns(UserInfo memory ); } contract Contract2{ struct UserInfo{ uint id ; string ime; } event UserEVENT (UserInfo UserInfo); UserInfo[] public newarr; function foo(address addr, uint i) external { // 先获取接口返回的结构体 IContract1.UserInfo memory remoteUser = IContract1(addr).arr(i); // 手动将字段赋值给本地结构体 UserInfo memory localUser = UserInfo(remoteUser.id, remoteUser.ime); emit UserEVENT(localUser); newarr.push(localUser); } }
这种方式虽然需要手动处理每个字段,但能满足必须使用本地结构体的场景。
这两种方案都能解决你遇到的类型转换错误,顺利实现从已部署的Contract1中读取结构体数组的需求。
内容的提问来源于stack exchange,提问作者gojic
相关产品推荐
相关产品推荐

