Ethereum 如何获取事务(非合同)的所有事件?

Ethereum 如何获取事务(非合同)的所有事件?,ethereum,solidity,Ethereum,Solidity,我希望使用web3获取Solidity合约发出的所有事件,但是.getPasteEvents()方法适用于合约 这将返回contractInstance的所有事件,但是,我的合约将调用也发出事件的其他合约 await contractInstance.getPastEvents("allEvents", {fromBlock: bn, toBlock: bn}); 我希望从事务中获取所有事件,而不是从合同中获取 或者,作为一种替代方法,甚至是一个块中的所有事件,我可以使用事务哈希对其进行过滤,

我希望使用web3获取Solidity合约发出的所有事件,但是.getPasteEvents()方法适用于合约

这将返回contractInstance的所有事件,但是,我的合约将调用也发出事件的其他合约

await contractInstance.getPastEvents("allEvents", {fromBlock: bn, toBlock: bn});
我希望从事务中获取所有事件,而不是从合同中获取

或者,作为一种替代方法,甚至是一个块中的所有事件,我可以使用事务哈希对其进行过滤,以得到我想要的。是否有一个函数可以返回块中的所有事件?我找过了,但找不到。我必须了解链中的每个合同,并分别获取事件吗?也许吧

我举了一个非常简单的例子来说明

实体代码:

pragma solidity 0.5.8;

contract contractA {
    event eventA();
    function methodA( address b ) public {
        emit eventA();
        contractB instanceB = contractB( b );
        instanceB.methodB();
    }
}

contract contractB {
    event eventB();
    function methodB() public {
        emit eventB();
    }
}
我用块菌来简化它。以下是迁移文件:

var contractA = artifacts.require("contractA");
var contractB = artifacts.require("contractB");

module.exports = function(deployer) {
  deployer.deploy(contractA);
  deployer.deploy(contractB);
下面是调用发出eventA的contractA methodA和发出eventB的contractB methodB的truffle javascript代码:

const contractA = artifacts.require("contractA");
const contractB = artifacts.require("contractB");

contract("contractA", async accounts => {

  thisAccount = accounts[0];

  it( "Simple test", async () => {

    const instanceA = await contractA.deployed();
    const instanceB = await contractB.deployed();

    const transaction = await instanceA.methodA( instanceB.address, { from: thisAccount } );

    const bn = transaction.receipt.blockNumber, txHash = transaction.tx;

    const allEventsA = await instanceA.getPastEvents("allEvents", {fromBlock: bn, toBlock: bn});
    const allEventsB = await instanceB.getPastEvents("allEvents", {fromBlock: bn, toBlock: bn});

    console.log("A");
    console.log( allEventsA );

    console.log("B");
    console.log( allEventsB );

  });

});
以下是输出:

$ truffle test test.js
Using network 'development'.


Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
  Contract: contractA
A
[
  {
    logIndex: 0,
    transactionIndex: 0,
    transactionHash: '0xe99db12863e5c0a0ae2c9c603d9d29f46a74d45ee9bf9f56d15f6f7bd1888058',
    blockHash: '0xfa65496b8cb6ecf5b729892836adf80aa883e6823bbdb2d1b8cdfe61b5c97256',
    blockNumber: 1573,
    address: '0x97519Ada953F882d61625125D5D68E7932250E9F',
    type: 'mined',
    id: 'log_d28138a2',
    returnValues: Result {},
    event: 'eventA',
    signature: '0x72f2637d8047e961ba6b558fdf63d428e9734bdf7ee2fb2b114f3b1aa65335c7',
    raw: { data: '0x', topics: [Array] },
    args: Result { __length__: 0 }
  }
]
B
[
  {
    logIndex: 1,
    transactionIndex: 0,
    transactionHash: '0xe99db12863e5c0a0ae2c9c603d9d29f46a74d45ee9bf9f56d15f6f7bd1888058',
    blockHash: '0xfa65496b8cb6ecf5b729892836adf80aa883e6823bbdb2d1b8cdfe61b5c97256',
    blockNumber: 1573,
    address: '0x00108B6A5572d95Da87e8b4bbF1A3DcA2a565ff7',
    type: 'mined',
    id: 'log_da38637d',
    returnValues: Result {},
    event: 'eventB',
    signature: '0x34a286cd617cdbf745989ac7e8dab3f95e8bb2501bcc48d9b6534b73d055a89c',
    raw: { data: '0x', topics: [Array] },
    args: Result { __length__: 0 }
  }
]
    ✓ Simple test (76ms)
正如你所看到的,我必须独立地要求签订每一份合同。我想知道是否有一个“transaction object”方法可以在一次调用中获取这两个事件,因为它们毕竟来自同一个事务

您可以想象这样一种情况:在同一事务中,事件从多个契约中发出


也许这是不可能的,但我想我还是会问的

通过调用
instanceA.methodA()
触发的事务称为内部事务,在尝试获取事件时不包括其事件

有一种方法可以从事务中获取所有事件,但有点麻烦:

1-使用
web3.eth.getTransactionReceivement()
获取发送收据。这为您提供了带有事件对象的日志数组,事件对象有三个重要字段:
地址
数据
主题

  • 地址
    ,合同地址是从中触发事件的地址
  • 数据
    ,事件的非索引参数
  • 主题
    ,事件签名的散列和索引参数的散列(如果有)
2-获得此信息后,使用
地址
获取合同abi。现在你有了这份合同可以触发的所有事件的列表,因为你有abi。散列所有事件签名,并找到与
主题
数组中的第一项匹配的签名。您可以使用
web3.eth.abi.encodeEventSignature()
检查事件签名的哈希。通过这种方式,您将发现它是哪个事件。还需要参数名

3-使用带有
web3.eth.abi.decodeLog的事件签名解码abi(输入、十六进制字符串、主题)

示例:
web3.eth.abi.decodeLog([{
键入:“字符串”,
名称:“myString”
},{
类型:“uint256”,
姓名:'我的号码',
索引:正确
},{
类型:“uint8”,
名称:'mySmallNumber',
索引:正确
}],
'0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000748656C6C6F2521000000000000000000000000000000000000000000000000000000000000',
['0x000000000000000000000000000000000000000000000000000000000000000000f310','0x0000000000000000000000000000000000000000000000000000000000000000000010']

你会得到:

结果{ “0”:“你好%!”, '1': '62224', '2': '16', myString:“你好%!”, 我的号码:“62224”, mySmallNumber:'16'



这里还解释了:

您能澄清一下吗?您希望所有合同中的所有事件都在一个块中吗?我真的希望所有事件都是由于一个事务而发出的,但我愿意接受一个块中的所有事件,因为这样我可以根据事件的事务id对它们进行过滤,这将实现我想要的。我已经修改了问题为了反映这种可能性,所有事件都源于特定合同?因此我调用(进行交易)对于contractA方法,该方法会发出一个事件,它也会调用contractB方法,此方法也会发出一个事件。我想同时获得两个事件,即我事务的所有事件……我觉得这很简单,但可能需要更好地解释。我现在给出完整的代码示例