gakonst / ethers-rs

Complete Ethereum & Celo library and wallet implementation in Rust. https://docs.rs/ethers
Apache License 2.0
2.5k stars 796 forks source link

how to parse a log from tx receipt #1810

Open imokoi opened 2 years ago

imokoi commented 2 years ago

Sorry to ask this question, but I didn't find any example of parsing the log in tx receipt.

what I have tried:

config a ERC20TransferEvent

#[derive(Debug, Default, EthEvent)]
pub struct Erc20TransferEvent {
    pub from: Address,
    pub to: Address,
    pub value: U256,
}

...

      let erc20_transfer_filter = Filter::new().topic0(ValueOrArray::Value(H256::from(
          keccak256("Transfer(address,address,uint256)"),
      )));
      let event_builder = Erc20TransferEvent::new(erc20_transfer_filter, &provider);

      let event = event_builder.parse_log(log.unwrap().clone()).unwrap();
      println!("event: {:?}", event);

it failed.

then I tried another way


        let params = vec![
            EventParam {
                name: "from".to_string(),
                kind: ParamType::Address,
                indexed: true,
            },
            EventParam {
                name: "to".to_string(),
                kind: ParamType::Address,
                indexed: true,
            },
            EventParam {
                name: "value".to_string(),
                kind: ParamType::Uint(256),
                indexed: fasle,
            },
        ];

        let event = Event {
            name: "Transfer".to_string(),
            inputs: params,
            anonymous: false,
        };

        let topics = log.topics.clone();
        let data = log.data.clone().to_vec();
        let my_event = event
            .parse_log(ethers::abi::RawLog {
                topics: topics,
                data,
            })
            .unwrap();
        println!("my_event: {:?}", my_event);

it succeeds. but I want to how to use the way 1.

so is there any example about paring log?

imokoi commented 2 years ago

logic of topic filter

        let log = receipt
            .logs
            .iter()
            .find(|log| {
                log.topics
                    .iter()
                    .find(|topic| {
                        **topic
                        == H256::from_str(
                            "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
                        )
                        .unwrap()
                    })
                    .is_some()
            })
            .unwrap();
imokoi commented 2 years ago

I got it.

I need to define my event like below

#[derive(Debug, Default, EthEvent, PartialEq, Eq)]
#[ethevent(name = "Transfer", abi = "Transfer(address,address,uint256)")]
pub struct Erc20TransferEvent {
    #[ethevent(indexed)]
    pub from: Address,
    #[ethevent(indexed)]
    pub to: Address,
    pub value: U256,
}

parse the log

let event = <Erc20TransferEvent as EthLogDecode>::decode_log(&ethers::abi::RawLog {
                topics,
                data,
            })
mattsse commented 2 years ago

yes, the indexed fields are required.

do you want to add an erc20 event parsing example?

imokoi commented 2 years ago

yes, the indexed fields are required.

do you want to add an erc20 event parsing example?

sure, I will post a PR later