获取实体映射的关键点



我试图在solidity contract 中获取映射到特定合同(不完全(的星形名称和地址的密钥

mapping(string=>address) nameOfAccounts;

我所期待的是一个类似于Javascript中的Object.keys(nameOfAccounts)的方法。有类似的方法吗?。或者我应该使用额外的CCD_ 2。额外的阵列可能会导致额外的气体成本(这不是我喜欢的选项(。请分享一些见解

我想知道如果不能获得钥匙,我是否还有其他方法可以做?

简单回答:如果合同没有提供映射的对象密钥列表,你就无法获得它。

长答案:

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

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

如果您没有存档节点的预算,您可以尝试Etherscan的API

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

还有另一个选项,反编译合同,并检查其输入,输入将具有密钥,然后扫描该合同的所有交易,并通过处理输入提取密钥(输入是tx.Data((字段(。如果你对合同有一些了解,或者如果你有消息来源,这个选项会更容易,这将是最简单的事情(处理输入(

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

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

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

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

点击此处了解更多信息。

尝试在Solidity中使用Goodmapping.sol而不是原始映射。

https://github.com/lidangzzz/GoodMapping.sol

这里有一个快速的例子:

// Import map uint256 => address
import "goodmapping/contracts/Map_UA.sol";
// A mapping uint256 => address
Map_UA private my_map; 
// insert some key-value pare
my_map.set(0x123,1);
my_map.set(0x234,2);
// get all keys 
address[] memory keys = my_map.keys();
// iterate each key-value pare
for (uint256 index = 0; index < keys.length; index++)
{
//get value 
bool bExist = false;
uint256 value = 0;
(bExist, value) = my_map.get(keys[index]);
}

获取映射变量键的最简单方法是使用SmartMuv工具。该工具提供了映射键及其值的列表,您可以使用它。

最新更新