如何在ethers.js ABI中定义结构体数组类型的返回值
解决方案
Ethers的人类可读ABI格式默认无法识别自定义结构体名称,需要把结构体显式声明为tuple类型,有两种常用修改方案:
方案1:使用人类可读ABI(无需修改为JSON格式)
直接将返回值中的Stake[]替换为对应结构的tuple数组声明,字段顺序和类型完全和你定义的Stake结构体对齐即可,修改后的ABI如下:
const stakingAbi = [ 'function getStakes(address user) external view returns (tuple(uint16 bonusPercentage, uint40 unlockTimestamp, uint128 amount, bool withdrawn)[])', 'function stake7Days(uint128 _amount) external whenNotPaused', 'function stake14Days(uint128 _amount) external whenNotPaused', 'function stake30Days(uint128 _amount) external whenNotPaused', 'function stake90Days(uint128 _amount) external whenNotPaused' ]
调用getStakes后返回的数组每一项都会自动解析为对应字段的对象,可以直接按属性名访问。
方案2:使用标准JSON格式ABI(兼容性更强)
如果后续还有更多自定义结构体,更推荐用标准JSON ABI,getStakes对应的ABI片段如下,完整ABI可以直接从合约编译产物的abi字段复制:
{ "inputs": [{"internalType": "address", "name": "user", "type": "address"}], "name": "getStakes", "outputs": [ { "internalType": "struct Stake[]", "name": "", "type": "tuple[]", "components": [ {"internalType": "uint16", "name": "bonusPercentage", "type": "uint16"}, {"internalType": "uint40", "name": "unlockTimestamp", "type": "uint40"}, {"internalType": "uint128", "name": "amount", "type": "uint128"}, {"internalType": "bool", "name": "withdrawn", "type": "bool"} ] } ], "stateMutability": "view", "type": "function" }
注意事项
tuple内的字段顺序必须和合约中定义的Stake结构体顺序完全一致,否则会出现数据解码错乱的问题。
内容的提问来源于stack exchange,提问作者Thimma
相关产品推荐
相关产品推荐

