foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.17k stars 1.7k forks source link

replace otterscan types with alloy's otterscan types #8298

Closed mattsse closed 2 months ago

mattsse commented 3 months ago

Component

Anvil

Describe the feature you would like

all of the otterscan types: https://github.com/foundry-rs/foundry/blob/e3021017b643e43e42a4c420b636a2ae947bf89f/crates/anvil/src/eth/otterscan/types.rs#L84-L84

should be available in alloy and can be replaced

https://github.com/alloy-rs/alloy/blob/440ee680f9b16c8813507bae501a4b72a3610f05/crates/rpc-types-trace/src/otterscan.rs#L25-L25

Additional context

No response

fedemagnani commented 3 months ago

could I take this?

klkvr commented 3 months ago

hey @fedemagnani assigned you

fedemagnani commented 3 months ago

Thank you for assigning me to this issue. There are several otterscan types which require implementation using anvil/src/eth/mem/Backend (take build() as an example.

Since implementation on Alloy's types is not possible being foreign types, which approach would you prefer?

1) Decorators wrapping Alloy's otterscan types 2) Definition of a BuildOts trait implmented by Alloy's otterscan types

Taking as example BlockDetails (which corresponds to OtsBlockDetails in anvil/src/eth/otterscan/types). With approach (1)

use alloy_rpc_types::trace::otterscan::BlockDetails as AlloyBlockDetails;

pub struct BlockDetails(AlloyBlockDetails);

// ... implements AsRef<AlloyBlockDetails>, From<AlloyBlockDetails> and AsMut<AlloyBlockDetails> for BlockDetails

impl BlockDetails {
    pub async fn build(block: Block, backend: &Backend) -> Result<Self> {
        //... implementation
    }
}

With approach (2)

use alloy_rpc_types::trace::otterscan::BlockDetails;

pub trait BuildOts: Sized {
    type Input;
    fn build(
        backend: &Backend,
        input: Self::Input,
    ) -> impl std::future::Future<Output = Result<Self>>;
}

impl BuildOts for BlockDetails {
    type Input = Block;
    async fn build(backend: &Backend, block: Block) -> Result<Self> {
        //... implementation
    }
}

Approach 2 might be useful in defining a shared interface among otterscan types and it would allow to use directly Alloy's types. However, it might need the definition of redundant types (one specific for each Alloy's type) to be set as Input associated type.

Which approach would you prefer? Is there any other better approach that you would recommend?

DaniPopes commented 3 months ago

I think we should just move the logic into either new/existing methods on Backend or free functions in otterscan/api.rs, the trait is excessive IMO