alloy icon indicating copy to clipboard operation
alloy copied to clipboard

[Bug] Incorrect events indexed from an anvil instance which are created via forge script

Open mesozoic-technology opened this issue 6 months ago • 1 comments

Component

node-bindings, rpc, other

What version of Alloy are you on?

├── alloy v0.1.4 │ ├── alloy-core v0.7.7 │ │ ├── alloy-primitives v0.7.7 │ │ │ ├── alloy-rlp v0.3.7 │ │ │ │ ├── alloy-rlp-derive v0.3.7 (proc-macro) │ │ │ │ ├── alloy-rlp v0.3.7 () │ │ └── alloy-sol-types v0.7.7 │ │ ├── alloy-primitives v0.7.7 () │ │ ├── alloy-sol-macro v0.7.7 (proc-macro) │ │ │ ├── alloy-sol-macro-expander v0.7.7 │ │ │ │ ├── alloy-sol-macro-input v0.7.7 │ │ │ ├── alloy-sol-macro-input v0.7.7 () │ ├── alloy-eips v0.1.4 │ │ ├── alloy-primitives v0.7.7 () │ │ ├── alloy-rlp v0.3.7 () │ │ ├── alloy-serde v0.1.4 │ │ │ ├── alloy-primitives v0.7.7 () │ ├── alloy-node-bindings v0.1.4 │ │ ├── alloy-genesis v0.1.4 │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-serde v0.1.4 () │ │ ├── alloy-primitives v0.7.7 () │ ├── alloy-provider v0.1.4 │ │ ├── alloy-chains v0.1.23 │ │ ├── alloy-consensus v0.1.4 │ │ │ ├── alloy-eips v0.1.4 () │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-rlp v0.3.7 () │ │ │ ├── alloy-serde v0.1.4 () │ │ ├── alloy-eips v0.1.4 () │ │ ├── alloy-json-rpc v0.1.4 │ │ │ ├── alloy-primitives v0.7.7 () │ │ ├── alloy-network v0.1.4 │ │ │ ├── alloy-consensus v0.1.4 () │ │ │ ├── alloy-eips v0.1.4 () │ │ │ ├── alloy-json-rpc v0.1.4 () │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-rpc-types-eth v0.1.4 │ │ │ │ ├── alloy-consensus v0.1.4 () │ │ │ │ ├── alloy-eips v0.1.4 () │ │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ │ ├── alloy-rlp v0.3.7 () │ │ │ │ ├── alloy-serde v0.1.4 () │ │ │ │ ├── alloy-sol-types v0.7.7 () │ │ │ ├── alloy-serde v0.1.4 () │ │ │ ├── alloy-signer v0.1.4 │ │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-sol-types v0.7.7 () │ │ ├── alloy-node-bindings v0.1.4 () │ │ ├── alloy-primitives v0.7.7 () │ │ ├── alloy-rpc-client v0.1.4 │ │ │ ├── alloy-json-rpc v0.1.4 () │ │ │ ├── alloy-transport v0.1.4 │ │ │ │ ├── alloy-json-rpc v0.1.4 () │ │ │ ├── alloy-transport-http v0.1.4 │ │ │ │ ├── alloy-json-rpc v0.1.4 () │ │ │ │ ├── alloy-transport v0.1.4 () │ │ ├── alloy-rpc-types-anvil v0.1.4 │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-serde v0.1.4 () │ │ ├── alloy-rpc-types-eth v0.1.4 () │ │ ├── alloy-signer-local v0.1.4 │ │ │ ├── alloy-consensus v0.1.4 () │ │ │ ├── alloy-network v0.1.4 () │ │ │ ├── alloy-primitives v0.7.7 () │ │ │ ├── alloy-signer v0.1.4 () │ │ ├── alloy-transport v0.1.4 () │ │ ├── alloy-transport-http v0.1.4 () │ ├── alloy-rpc-client v0.1.4 () │ └── alloy-rpc-types v0.1.4 │ ├── alloy-rpc-types-eth v0.1.4 () │ └── alloy-serde v0.1.4 () ├── alloy-sol-types v0.7.7 (*)

Operating System

macOS (Apple Silicon)

Describe the bug

I have a rust script that starts up an anvil instance.

I then use let mut output = std::process::Command::new("forge").... to run a forge script against this anvil instance, giving it the option -vvvv, which prints the script's call trace out.

Examining this calltrace, I see the events I expect to be emitted being emitted.

Then I use an alloy provider to index these events from the anvil instance.

However, the events I get are different. Notably in the timestamp that I put in the events.

It seems that the calltrace is reporting something different than is actually happening in the execution in the anvil node.

Here's a truncated version of my script. The forge script basically emits a number of KinoRegistered events.

use alloy::{
    hex,
    node_bindings::Anvil,
    primitives::{keccak256, Address, Log, B256, U256, Bytes},
    providers::{Provider, ProviderBuilder},
    rpc::types::eth::Filter,
    sol_types::{SolEvent, SolType, SolValue},
    sol
};
use regex::Regex;
use rust_decimal::prelude::*;
use rust_decimal::MathematicalOps;
use std::collections::HashMap;
use std::process::Command;
use std::thread;
use std::time::Duration;
use tokio::main;

sol!(
    event KinoRegistered(
        address indexed who, 
        bytes32 indexed node, 
        address indexed delegate, 
        uint256 amount,
        uint256 end,
        bytes32 root
    );
);

#[main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {

    let mut anvil = Anvil::new()
        .block_time(4)
        .try_spawn()?;

    let Ok(mut provider) = ProviderBuilder::new()
        .on_builtin(&anvil.endpoint()).await else { todo!() };

    provider.raw_request(
        std::borrow::Cow::Borrowed("evm_setNextBlockTimestamp"), 
        [2037450657]
    ).await?;

    let blockno = provider.get_block_number().await?;
    let block = provider
        .get_block_by_number(blockno.into(), true)
        .await?;

    let mut output = Command::new("forge")
        .arg("script")
        .arg("script/KinoVotingRegistration.s.sol:KVRTestFixtures")
        .arg("--rpc-url")
        .arg(&anvil.endpoint())
        .arg("--broadcast")
        .arg("-vvvv")
        .current_dir("..")
        .output()
        .expect("failed");

    let mut KVR_ADDRESS = Address::default();

    if output.status.success() {

        let stdout = String::from_utf8(output.stdout.clone()).unwrap();

        println!("success {}", stdout);

        let re = Regex::new(r"kvr: address (0x[a-fA-F0-9]{40})").unwrap();
        
        if let Some(captures) = re.captures(&stdout) {
            KVR_ADDRESS = Address::from_str(&captures[1]).unwrap();
            println!("Extracted KVR_ADDRESS: {}", KVR_ADDRESS);
        } else {
            println!("Failed to extract KVR_ADDRESS");
        }

    } else {
        println!(
            "error {}",
            String::from_utf8(output.stderr).unwrap()
        );
    }

    let registration_filter = Filter::new()
        .address(KVR_ADDRESS)
        .events([KinoRegistered::SIGNATURE]);

    let Ok(registration_events) = provider
        .get_logs(&registration_filter)
        .await else { todo!() };

If you need an executable example, I can work on that when I have a moment.

mesozoic-technology avatar Aug 04 '24 17:08 mesozoic-technology