Skip to content

Conversation

@jmg-duarte
Copy link
Contributor

@jmg-duarte jmg-duarte commented Oct 27, 2025

Description

Implements bindings generation in build.rs, adding this allows

  1. Generated code to be inspected manually and "cmd-click"ed into
  2. Faster incremental compilation since the code can be cached unlike macros

Changes

  • New contracts-generate crate to simplify build.rs code
  • Generate bindings in contracts build.rs
  • Migrate everything without changing any module paths
  • Moved away from the Provider re-export (contracts::alloy::Provider -> alloy::providers::DynProvider)
  • Removes the ethcontract re-export from the contracts crate
  • Removes now unused code (some inconsistent tests and dummy legacy things)

How to test

Run existing tests & compile

@jmg-duarte jmg-duarte marked this pull request as ready for review November 4, 2025 11:25
@jmg-duarte jmg-duarte requested a review from a team as a code owner November 4, 2025 11:25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why this needs to live in a separate crate and can't be made part of the existing contracts crate? Seems appropriate to have this in one place, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is build.rs code only, IMO it doesn't make sense to litter the main crate with this. Though I can move it to the build.rs of the contracts crate

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having this code in the contracts crate makes the most sense. It's not like it would be useful for anything else.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree on keeping everything in the contracts crate.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, let's keep it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, please review the new build.rs. Keep in mind that I can't move any of the code inside build.rs to the crate because the build.rs is what builds the crate

all_derives: bool,
) -> eyre::Result<proc_macro2::TokenStream> {
let bindings_path = self.bindings_path(bindings_folder.as_ref());
let mut macrogen = SolMacroGen::new(bindings_path, self.name.clone());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check if this also supports json5? Would be nice to have the ability to add comments in the ABI file. This is just a nice to have so I wouldn't change the PR if this is not supported out of the box.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new dependencies pull in hundreds of additional transient dependencies. If there is a way to just expand the sol! marcro we've been using before this should do the trick, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer the case. Furthermore, expanding the sol! macro on the side and moving the code without external tools doesn't seem to be possible

cc @squadgazzz @m-sz

Comment on lines 360 to 380
struct NetworkArm(u64, (String, Option<u64>));

impl ToTokens for NetworkArm {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let chain_id = self.0;
let address = &self.1.0;
let block_number = match self.1.1 {
Some(block) => quote::quote! {Some (#block)},
None => quote::quote! {None},
};
tokens.extend(quote::quote! {
#chain_id => Some((::alloy::primitives::address!(#address), #block_number))
});
}
}

impl From<(u64, (String, Option<u64>))> for NetworkArm {
fn from((chain_id, info): (u64, (String, Option<u64>))) -> Self {
Self(chain_id, info)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to split this PR? It contains too many changes that are hard to review. Can the initial version live without these helpers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one here is to solve Martin's query in #3827 (comment)

I can split them though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't notice this comment. Alright, no worries. I'll try to review again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no clue how to review this other than by asking AI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do them one by one. I did this whole with AI too and did multilple rounds with different contexts. But this was more about proving that I was able to migrate everything with minimal changes on the main codebase

@squadgazzz squadgazzz requested a review from Copilot November 6, 2025 12:31
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors contract binding generation to use a build script approach with auto-generated code. The migration moves from runtime contract instance creation to compile-time code generation.

Key changes:

  • Introduces contracts-generate crate with custom binding generation
  • Replaces runtime InstanceExt trait with compile-time generated deployment info
  • Removes legacy web3 dummy transport and macros
  • Updates type references from contracts::alloy::Provider to alloy::providers::DynProvider

Reviewed Changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
crates/contracts-generate/Cargo.toml New crate for build-time contract generation
crates/contracts-generate/src/lib.rs Core generation logic with network deployment mapping
crates/contracts/build.rs Build script defining all contract deployments
crates/contracts/src/lib.rs Simplified to export generated bindings only
crates/contracts/src/alloy.rs Deleted - replaced by generated code
crates/contracts/.gitignore Ignores generated src/alloy directory
Multiple usage files Updated to remove InstanceExt imports and use DynProvider

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@socket-security
Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedprettyplease@​0.2.378210093100100
Addedwalkdir@​2.5.010010095100100

View full report

Copy link
Contributor

@squadgazzz squadgazzz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants