You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ethers.js无法返回映射中结构体完整对象的问题排查

问题原因及解决办法

核心原因:Solidity的mapping无法被整体读取

你拿不到完整结构体的问题不是Ethers.js的遗漏,而是Solidity本身的机制限制:

  • Solidity中的mapping是键值对存储结构,链上不会保存mapping的所有键列表,也没有内置方法能直接返回整个mapping的内容。
  • 合约自动生成的payment_splitters_registry getter函数,只能返回结构体中可直接序列化的类型(比如你的total,本质是Counters.Counter对应的uint256数值),而mapping无法被自动序列化返回。

解决方法

要获取用户的所有payment_splitters数据,需要在合约层面做额外处理:

  1. 修改User结构体,新增数组记录所有已使用的mapping键:
struct User {
    Counters.Counter total;
    mapping(uint => address) payment_splitters;
    uint[] splitterKeys; // 新增:保存所有被赋值过的uint键
}
  1. 往payment_splitters添加新键值对时,同步把键存入数组:
function addSplitter(uint key, address splitter) public {
    User storage user = payment_splitters_registry[msg.sender];
    user.payment_splitters[key] = splitter;
    user.splitterKeys.push(key); // 记录新增的键
}
  1. 在合约中新增函数,返回指定用户的splitterKeys数组:
function getUserSplitterKeys(address userAddr) public view returns(uint[] memory) {
    return payment_splitters_registry[userAddr].splitterKeys;
}
  1. 在Ethers.js中先获取所有键,再逐个拉取对应地址:
// 获取用户的所有splitter键
const splitterKeys = await myContract.getUserSplitterKeys(userAddress);
// 遍历键获取对应地址
const paymentSplitters = {};
for (const key of splitterKeys) {
    paymentSplitters[key] = await myContract.payment_splitters_registry(userAddress, key);
}
// 组合完整用户数据
const userData = await myContract.payment_splitters_registry(userAddress);
const fullUser = { total: userData.total, payment_splitters: paymentSplitters };

如果只是想获取某个特定键对应的地址,直接调用await myContract.payment_splitters_registry(userAddress, targetKey)即可。

内容的提问来源于stack exchange,提问作者0xJesus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:01:43