Transactions

我怎樣才能找到使用者在合約上製定某個事件的區塊?

  • December 24, 2021

我正在嘗試建構一個 web3.py 程序來接收給定使用者的地址,並返回交易的 ETH 數量,因為他們為 Uniswap 交易所增加了流動性。Uniswap 是乙太坊平台上的智能合約。

Uniswap 合約有一個“AddLiquidity”方法,允許使用者添加資金,我想知道給定使用者何時執行此操作。

我查看了文件以了解如何執行此操作。我正在通過 infura 節點訪問區塊鏈,文件似乎說在 infura 上你不能使用過濾器。

在契約文件中,似乎我可以通過 events 對象執行此操作,但無法使其正常工作。認為事件日誌可能很重要,但正如我所說,我一直在努力讓其中的任何一個完成我希望的事情。

如果您需要任何進一步的資訊來幫助我,請告訴我,謝謝!

智能合約

pragma solidity 0.5.1;


contract Uniswap {

  event Triggered(address indexed user);

  function addLiquidity() external {
      emit Triggered(msg.sender);
  }

}

Javascript 事件過濾

var sha3HashOfTheEvent = web3.sha3("event Triggered(address)");
var filterOptions = {
   fromBlock: 0,
   toBlock: 'latest',
   topics:[sha3HashOfTheEvent]
}
filter.watch(function(error, result){
   if(!error){
      console.log("The event has been triggered.......")
      filter.stopWatching();
   }
});

希望它會幫助你。

這些將是步驟

  • 以 Uniswap ABIweb3.Contract為基礎,建構對象
  • 掃描AddLiquidity從區塊零到最後一個主網區塊的所有事件
  • 根據這些建立您自己的數據庫/存款清單

這是一些類似的程式碼來Transfer獲取令牌的所有事件:

   def scan_chunk(self, start_block, end_block) -> Set[str]:
       """Populate TokenHolderStatus for certain blocks.
       :return: Set of addresses where balance changes between scans.
       """

       mutated_addresses = set()
       token = self.get_token_contract(self.address)

       # Discriminate between ERC-20 transfer and ERC-667
       # The latter is not used anywhere yet AFAIK
       Transfer = token.events.Transfer("from", "to", "value")
       Issued = token.events.Issued("to", "value")
       block_timestamps = {}
       get_block_timestamp = self.get_block_timestamp

       # Cache block timestamps to reduce some RPC overhead
       # Real solution would be smarter models around block
       def get_block_when(block_num):
           if not block_num in block_timestamps:
               block_timestamps[block_num] = get_block_timestamp(block_num)
           return block_timestamps[block_num]

       for event_type in [Issued, Transfer]:

           # events = event_type.createFilter(fromBlock=start_block, toBlock=end_block).get_all_entries()

           events = getLogs(event_type, fromBlock=start_block, toBlock=end_block)

           # AttributeDict({'args': AttributeDict({'from': '0xDE5bC059aA433D72F25846bdFfe96434b406FA85', 'to': '0x0bdcc26C4B8077374ba9DB82164B77d6885b92a6', 'value': 300000000000000000000}), 'event': 'Transfer', 'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0x973eb270e311c23dd6173a9092c9ad4ee8f3fe24627b43c7ad75dc2dadfcbdf9'), 'address': '0x890042E3d93aC10A426c7ac9e96ED6416B0cC616', 'blockHash': HexBytes('0x779f55173414a7c0df0d9fc0ab3fec461a66ceeee0b4058e495d98830c92abf8'), 'blockNumber': 7})
           for e in events:
               idx = e["logIndex"]  # nteger of the log index position in the block. null when its pending log.
               if idx is None:
                   raise RuntimeError("Somehow tried to scan a pending block")

               if e["event"] == "Issued":
                   # New issuances pop up from empty air - mark this specially in the database.
                   # Also some ERC-20 tokens use Transfer from null address to symbolise issuance.
                   from_ = self.TokenScanStatus.NULL_ADDRESS
               else:
                   from_ = e["args"]["from"]
                   mutated_addresses.add(e["args"]["from"])

               block_when = get_block_when(e["blockNumber"])

               self.create_deltas(e["blockNumber"], block_when, e["transactionHash"].hex(), idx, from_, e["args"]["to"], e["args"]["value"])
               self.logger.debug("Imported %s, token:%s block:%d from:%s to:%s value:%s", e["event"], self.address, e["blockNumber"], from_, e["args"]["to"], e["args"]["value"])

               mutated_addresses.add(e["args"]["to"])

       return mutated_addresses

您可以在此處找到完整的原始碼

如果您事先知道使用者地址,您也很可能能夠根據此地址進行過濾,因此您無需掃描所有事件。每個 Solidity 事件可以有 4 個索引參數,允許您在乙太坊節點級別過濾這些事件,這意味著內部乙太坊節點數據庫允許您查詢它們。但是,如果有很多事件,乙太坊節點可能無法快速響應這些查詢,無論如何您都需要建構自己的事件數據庫。

引用自:https://ethereum.stackexchange.com/questions/74000