【问题标题】:Get Keys of Solidity mapping获取 Solidity 映射的密钥
【发布时间】:2021-01-01 12:28:07
【问题描述】:

我试图在solidity合约中获取特定合约(不完全是)星名和地址的映射键

mapping(string=>address) nameOfAccounts;

我期待的是像 Javascript 中的 Object.keys(nameOfAccounts) 这样的方法。有没有类似的方法。。或者我应该使用额外的array。额外的 Array 可能会导致额外的 gas 成本(这不是我喜欢的选项)。请分享一些见解

我想知道如果不能选择获取密钥,是否还有其他方法可以做?

【问题讨论】:

  • 您已标记了多个项目,但它可能与这些主题有关。此外,您需要详细说明您的问题,就好像 javascript 程序员可能不知道什么是区块链一样。我想你的问题应该是在 javascript 中,你可以在 javascript 中的 filter/map 方法中传递你的逻辑!
  • 我编辑了问题并删除了 JavaScript 标记以保护问题
  • 好的 mikko,谢谢
  • 为什么不只保留一个数组来跟踪键?如果不在地图中,则仅附加?

标签: blockchain ethereum solidity smartcontracts


【解决方案1】:

简答:如果合约没有提供 map 的对象键列表,你是拿不到的。

长答案:

但由于区块链是公共的东西,你可以得到任何东西。 要获取地图的所有键,您需要这样做:

  • 设置存档节点并启用跟踪(您需要 9 TB 的磁盘,带有 SSD 缓存)
  • 获取对合约的所有调用的跟踪并搜索SSTORE操作码(指令)
  • SSTORE 指令从堆栈中弹出 2 个参数,Loc(位置)和 Val(值)。位置是您要寻找的关键。

如果你没有归档节点的预算,你可以试试 Etherscan 的 API

关于如何读取合约存储的SO上有答案,可能有用。

还有另一种选择,反编译合约,并检查其输入,输入将有密钥,然后扫描该合约的所有交易,并通过处理输入提取密钥(输入是 tx.Data()场地)。如果您对合同有一些了解,或者如果您有来源,则此选项会更容易,这将是最简单的事情(处理输入)

StateDB 对象类型中还有一个名为ForEachStorage() 的函数。它没有来自 RPC api 的前端,但通过一些努力,您可以实现自己的 RPC 函数来访问它并将其放在完整节点上。这个函数接受合约的地址和一个闭包函数,它会遍历整个合约的存储。来源:https://github.com/ethereum/go-ethereum/blob/0a3993c558616868e35f9730e92c704ac16ee437/core/state/statedb.go#L634 您唯一需要知道的是密钥是如何构建的,而这只能从合约源中知道。

【讨论】:

  • 9 TB 的 ssd 缓存?你不说..让我们都卖掉我们的肝脏来迭代一个映射为什么我们不..只做 mapping.keys() 然后迭代它怎么样?
【解决方案2】:

迭代键的最佳方法是,当添加键时,您还会发出一个 Solidity 事件。

您从事件日志中获取密钥。这可以在客户端(JavaScript、Python)完成,但不能在 Solidity 本身内完成,因为 EVM 无法访问事件数据。

由于执行受限环境中的效率原因,Solidity/EVM 不存储可迭代键。

More information here.

【讨论】:

    猜你喜欢
    • 2019-02-26
    • 2018-07-08
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2019-01-05
    • 2021-04-28
    • 1970-01-01
    相关资源
    最近更新 更多