Skip to content

Conversation

QYuQianchen
Copy link
Contributor

@QYuQianchen QYuQianchen commented May 21, 2025

Closes #7159

With Foundry's nightly release on May 20th, the generated contract bindings are compatible with alloy v1.0.4
Thus bump the alloy used in the crate to v1

Note that due to a known issue foundry-rs/foundry#10586, some unit tests around domain separator are skipped.

@Copilot Copilot AI review requested due to automatic review settings May 21, 2025 10:36
@QYuQianchen QYuQianchen self-assigned this May 21, 2025
Copy link
Contributor

coderabbitai bot commented May 21, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough
## Walkthrough

This change upgrades the `alloy` dependency to version 1.0.4 and systematically refactors the codebase and generated contract bindings to align with the new stable v1 API. It simplifies generics, removes redundant tuple field accesses, updates method names, enhances serialization support, and adjusts ABI decoding and event interfaces throughout Rust and Solidity test code.

## Changes

| File(s) / Path(s)                                                                                      | Change Summary |
|--------------------------------------------------------------------------------------------------------|---------------|
| Cargo.toml, ethereum/bindings/Cargo.toml                                                               | Updated `alloy` to v1.0.4; enabled `serde` derive feature. |
| flake.nix, justfile                                                                                    | Updated foundry source repo/branch; changed forge bind flags; added smart-contract-test recipe. |
| chain/indexer/src/handlers.rs                                                                          | Removed redundant boolean from event decoding calls. |
| chain/rpc/src/client.rs, hopli/src/environment_config.rs, hopr/hopr-lib/tests/common/mod.rs            | Replaced `.on_client(rpc_client)` with `.connect_client(rpc_client)`. |
| chain/rpc/src/rpc.rs, hopli/src/methods.rs, chain/types/src/lib.rs, chain/types/src/utils.rs           | Simplified generics (removed `()`/`T`), updated method calls, removed tuple field accesses, updated contract instance types. |
| ethereum/bindings/src/codegen/* (all contract/event files)                                             | Regenerated for alloy v1: removed transport generic, added serialization derives, changed event/call decoding signatures, simplified return types and ABI decoding, improved error/event struct definitions. |
| chain/actions/src/payload.rs, hopli/src/win_prob.rs, hopr/hopr-lib/tests/chain_integration_tests.rs    | Removed unnecessary tuple field accesses after contract calls. |
| ethereum/contracts/test/Channels.t.sol, ethereum/contracts/test/node-stake/NodeSafeRegistry.t.sol      | Changed fuzz test parameter types from `uint256` to `uint64` for chain ID, adjusted bounds. |
| ethereum/contracts/test/static/stake/HoprStakeBase.t.sol                                               | Reduced upper bound for elapsed time in tests. |
| ethereum/contracts/Makefile, Makefile                                                                 | Added comment about Foundry issue; updated test filters to exclude domain separator tests. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant App as Application/CLI
    participant Provider as Alloy Provider
    participant Contract as Contract Binding
    participant RPC as RPC Client

    App->>Provider: connect_client(rpc_client)
    Provider->>RPC: Send JSON-RPC requests
    App->>Contract: Call contract method (no redundant generics)
    Contract->>Provider: Use alloy v1 API
    Contract->>App: Return decoded result (no tuple destructuring)

Assessment against linked issues

Objective (Issue #) Addressed Explanation
Upgrade to stable latest v1 release of alloy-rs (#7159)

Possibly related PRs

Suggested labels

crate:hopr-chain-api

Suggested reviewers

  • NumberFour8
  • Teebor-Choka

</details>

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=hoprnet/hoprnet&utm_content=7171):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@QYuQianchen QYuQianchen added toolchain Developer and product happiness effort:medium time needed to complete review labels May 21, 2025
@github-project-automation github-project-automation bot moved this to To triage in hoprnet May 21, 2025
Copy link
Contributor

@Copilot 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 upgrades the crate to use Alloy v1, updating both manual and generated code to match the new provider APIs and serialization requirements.

  • Replace deprecated .on_client calls with .connect_client in environment setup
  • Regenerate all contract bindings to use the new Provider<N> generic form and add serde derives
  • Adjust utility and RPC helper signatures by removing the old Transport type parameter and updating serialization/bytes conversions

Reviewed Changes

Copilot reviewed 38 out of 39 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
hopli/src/environment_config.rs Swapped .on_client for .connect_client to match the new Alloy provider API
ethereum/bindings/src/codegen/* Regenerated codegen to remove Transport type, add serde::{Serialize,Deserialize} and rename conversion methods
ethereum/bindings/Cargo.toml Added serde = { features = ["derive"] } so generated code can use derive macros
chain/types/src/utils.rs Removed the unused T generic from helper functions signatures
chain/rpc/src/rpc.rs Updated RPC imports, removed . _0 unwraps, and adapted byte conversions for U56/U256
Files not reviewed (1)
  • flake.nix: Language not supported
Comments suppressed due to low confidence (4)

chain/rpc/src/rpc.rs:207

  • Calling .to_be_bytes_vec() allocates a new Vec<u8>. Use .to_be_bytes() (fixed-size array) or borrow the underlying bytes to avoid unnecessary heap allocations.
Ok(Balance::new(token_balance.to_be_bytes_vec(), BalanceType::HOPR))

chain/rpc/src/rpc.rs:16

  • [nitpick] The nested use alloy::{ rpc::{ ... }} import style is harder to scan. Consider flattening or grouping imports consistently (e.g. use alloy::rpc::{client::RpcClient, types::{Block, TransactionRequest}};) to match the surrounding code.
use alloy::{ rpc::{ client::RpcClient, types::{Block, TransactionRequest}, }, };

chain/types/src/utils.rs:69

  • The doc comment above still references generic <T, P, N>, but the signature now omits T. Please update or remove outdated type parameters in the documentation so it matches the new signature.
pub async fn mint_tokens<P, N>(hopr_token: HoprTokenInstance<P, N>, amount: U256) -> ContractResult<Option<u64>>

ethereum/bindings/Cargo.toml:12

  • The derive feature enables Serialize/Deserialize, but ensure the workspace’s serde version and features align with all generated code (which now uses #[derive(serde::Serialize, serde::Deserialize)]).
serde = { workspace = true, features = ["derive"] }

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 13

🔭 Outside diff range comments (5)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (1)

98-116: 🛠️ Refactor suggestion

Deriving Default on event structs is potentially misleading

#[derive(Default)] creates a zero-initialised Address (0x000…) for safeAddress/nodeAddress, which is never a valid run-time value for these fields.
If downstream code (e.g. in tests) calls DergisteredNodeSafe::default() the resulting value will be semantically invalid and could silently propagate.

-#[derive(serde::Serialize, serde::Deserialize)]
-#[derive(Default, Debug, PartialEq, Eq, Hash)]
+#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Hash)]

Consider implementing an explicit impl Default that panics, or drop the derive completely.

ethereum/bindings/src/codegen/hoprledger.rs (1)

95-112: 🛠️ Refactor suggestion

Same Default concern on event struct

See previous comment – defaulting a FixedBytes<32> domain separator to 0x00… is unlikely to be meaningful.
Dropping the derive avoids accidental misuse.

ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (1)

78-96: 🛠️ Refactor suggestion

Default derive again – risk of invalid placeholder addresses

As with the other bindings, generating a zero address for moduleImplementation / instance invites accidental misuse.
Recommend dropping Default or replacing it with an implementation that deliberately panics (unreachable!()).

ethereum/bindings/src/codegen/hoprdummyproxyfornetworkregistry.rs (1)

2645-2690: ⚠️ Potential issue

Selector arrays must be sorted for binary_search

binary_search assumes the slice is sorted; if the order of
SELECTORS changes during code-gen the lookup can return an invalid index,
triggering the wrong decode shim or a panic.

Add a post-generation sort or switch to a map-based lookup (e.g. phf) to make
the code resilient to ordering issues.

Also applies to: 2839-2854, 2856-2864

ethereum/bindings/src/codegen/hoprwinningprobabilityoracle.rs (1)

263-268: ⚠️ Potential issue

Compile-time failure – invalid NAME constant syntax

stringify!(@ name) is not legal Rust syntax – the @ token is invalid outside of the experimental macro system.
The file will fail to compile at this line, breaking every downstream crate that depends on these bindings.

-            /// The Solidity type name.
-            pub const NAME: &'static str = stringify!(@ name);
+            /// Solidity type name – hard-code because code-gen failed to inject it.
+            pub const NAME: &'static str = "WinProb";

If the value needs to stay in sync with Solidity, please have the code-generator emit the proper identifier instead of the bogus placeholder.

♻️ Duplicate comments (2)
chain/rpc/src/client.rs (1)

905-906: Same mechanical replacement duplicated throughout the test suite

All these lines repeat the exact pattern verified in the previous comment (replace .on_client with .connect_client). The earlier assessment therefore applies unchanged.

Also applies to: 934-935, 967-968, 999-1000, 1030-1030, 1075-1076, 1111-1112, 1165-1166, 1200-1201, 1275-1276, 1331-1332, 1439-1440, 1496-1497

ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (1)

195-210: Consistency: duplicate of previous remark

Same Default concern applies to NewHoprNodeStakeSafe.

🧹 Nitpick comments (19)
chain/rpc/src/rpc.rs (2)

218-220: Unnecessary allocation when copying win-probability bytes

to_be_bytes_vec() allocates, then copy_from_slice copies into a fixed array. You can avoid the allocation entirely:

-let mut encoded: EncodedWinProb = Default::default();
-encoded.copy_from_slice(&encoded_win_prob.to_be_bytes_vec());
+let encoded: EncodedWinProb = encoded_win_prob.to_be_bytes();

This removes one heap allocation and one copy.


227-228: Minor style: use existing Balance::new helper consistently

You already call BalanceType::HOPR.balance(...) which internally constructs Balance. That’s fine, but to stay DRY you could reuse the helper for the native branch as well (lines 199-206).

ethereum/bindings/src/codegen/hoprchannelsevents.rs (1)

524-532: Cloning the provider may be expensive – expose an Arc helper?

with_cloned_provider deep-clones the provider every time it is called.
For providers backed by heavy state (HTTP pools, signer caches, etc.) this can incur unnecessary allocations.

Consider an ergonomic helper that wraps the provider in Arc<P> once and reuses cheap Arc::clone calls:

-pub fn with_cloned_provider(self) -> HoprChannelsInstance<P, N> {
+pub fn with_arc_provider(self) -> HoprChannelsInstance<alloc::sync::Arc<P>, N> {
+    use alloc::sync::Arc;
     HoprChannelsInstance {
         address: self.address,
-        provider: ::core::clone::Clone::clone(&self.provider),
+        provider: Arc::new(self.provider.clone()),
         _network: ::core::marker::PhantomData,
     }
 }

Not blocking, but worth considering for high-throughput applications.

ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (2)

172-190: Default derive on event structs can create invalid states

Every event struct (Deregistered, Registered, …) now derives Default.
The synthesized value contains zeroed Addresses and false booleans, which can never appear on-chain and may be misleading if accidentally used in production code.

If Default is not strictly required, drop the derive; otherwise create a custom implementation that panics or returns None to avoid accidental misuse.

-#[derive(serde::Serialize, serde::Deserialize)]
-#[derive(Default, Debug, PartialEq, Eq, Hash)]
+#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq, Hash)]

Same remark applies to every event struct in this file.


1330-1335: with_cloned_provider emits a full clone – prefer Arc pattern

Same remark as for hoprchannelsevents.rs: cloning a provider with internal connection pools can be heavy.
Offering an Arc-based helper (or documenting that P should usually be an Arc<ProviderImpl>) can save resources.

ethereum/bindings/src/codegen/hoprledger.rs (3)

208-225: Default on zero-parameter call structs adds little value

LEDGER_VERSIONCall/ledgerDomainSeparatorCall/updateLedgerDomainSeparatorCall are unit-like; the implicit Default is identical to Self {} / Self.
Consider dropping #[derive(Default)] to keep the generated code minimal (compile time + binary size).


642-646: Empty derive list triggers an unnecessary compiler warning

#[derive()] with an empty list compiles but emits warning: empty trait list.
Simply remove the attribute:

-#[derive(serde::Serialize, serde::Deserialize)]
-#[derive()]
+#[derive(serde::Serialize, serde::Deserialize)]

746-798: ABI decode helpers – consider unifying validate / non-validate paths

Good call adding abi_decode_raw_validate, but the duplicate shim tables inflate code size.
You can DRY this up by:

let decode = if validate {
    DECODE_VALIDATE_SHIMS[idx]
} else {
    DECODE_SHIMS[idx]
};
decode(data)

Generated code will be ~50 % smaller while preserving behaviour.

ethereum/bindings/src/codegen/hoprwinningprobabilityoracleevents.rs (2)

110-116: Constant NAME looks like a code-gen artefact

pub const NAME: &'static str = stringify!(@ name); expands to "@ name" at run time, which is probably not the intended Solidity type name ("WinProb").
Although purely cosmetic, this string may propagate to log/error messages or documentation helpers.

- pub const NAME: &'static str = stringify!(@ name);
+ pub const NAME: &'static str = "WinProb";

66-71: Consider deriving Copy for the new-type wrapper

WinProb is a zero-cost wrapper around U56 (itself Copy). Adding the Copy derive will:

  • eliminate the need for clone() in generic code,
  • keep semantics in line with the primitive it wraps.
- #[derive(serde::Serialize, serde::Deserialize)]
- #[derive(Default, Debug, PartialEq, Eq, Hash)]
+ #[derive(serde::Serialize, serde::Deserialize, Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]
ethereum/bindings/src/codegen/hoprannouncementsevents.rs (2)

110-128: Hash derive on baseMultiaddr: String could bloat hashing costs

std::string::String implements Hash, but its hashing cost scales with the full byte length.
If you only need equality checks or serialization, you can drop Hash (or switch to Box<str> / Arc<str> if sharing is common).

Not a blocker, just flagging in case the enum is used as a map key in hot paths.


581-588: Reuse pattern matches for provider bound

Every instantiation function (new, deploy, deploy_builder) repeats the bound

P: alloy_contract::private::Provider<N>,
N: alloy_contract::private::Network,

Code-gen can place a where-clause on the impl block instead; that removes repetition and shortens generated code.
Leaving this here in case you plan another generator pass.

ethereum/bindings/src/codegen/hoprcrypto.rs (2)

62-71: Derive Copy for unit errors

InvalidCurvePoint, InvalidFieldElement, and InvalidPointWitness are unit structs.
Deriving Copy (in addition to Clone) incurs no cost and avoids inadvertent moves:

- #[derive(serde::Serialize, serde::Deserialize)]
- #[derive(Default, Debug, PartialEq, Eq, Hash)]
+ #[derive(serde::Serialize, serde::Deserialize, Copy, Clone, Default, Debug, PartialEq, Eq, Hash)]

Repeat for the other two error structs.


537-568: Potentially remove _network phantom when N = Ethereum

The default type parameter already represents the canonical network.
If you never instantiate with a different N, code size can shrink (and readability improve) by dropping the extra generic and the PhantomData.

Not urgent—only worth it if binary size matters.

ethereum/bindings/src/codegen/hoprdummyproxyfornetworkregistry.rs (1)

923-951: Boiler-plate for return handling can be DRY’ed up

tokenize_returns, abi_decode_returns, and abi_decode_returns_validate
implement identical logic for every single‐value return. Consider generating a
blanket helper/macro instead of repeating ~20 lines per function; this will:

  • Reduce the generated code size by several hundred lines per binding.
  • Speed up incremental compilation.
  • Make the template easier to maintain.

Also applies to: 1087-1115, 1230-1258, 1386-1414, 1529-1557

ethereum/bindings/src/codegen/hoprannouncements.rs (1)

2095-2104: Redundant multicallReturn struct – dead code & extra maintenance cost

After refactoring, multicallCall::Return is now a plain Vec<Bytes>.
The public multicallReturn wrapper remains but is no longer used anywhere except as an intermediate inside the auto-generated decode helpers. Keeping an exported struct that is never intended to be constructed by users:

  • inflates the public API surface,
  • creates confusion between the “actual” return type and the unused wrapper,
  • adds a (small) compile-time cost.

Unless another part of the codebase explicitly relies on multicallReturn, consider pruning it and decoding directly into Vec<Bytes>.

If you still need the wrapper internally, mark it pub(crate) or hide it with #[doc(hidden)] to avoid exposing noise to downstream crates.

Also applies to: 2169-2181

ethereum/bindings/src/codegen/hoprnodestakefactory.rs (3)

172-180: Consolidate duplicate derive attributes to improve readability

Each struct currently has two consecutive #[derive(...)] attributes. Although perfectly legal, this adds noise to already-verbose generated code. Keeping all traits in a single derive keeps the file shorter and makes manual diff reviews easier.

-#[derive(serde::Serialize, serde::Deserialize)]
-#[derive(Default, Debug, PartialEq, Eq, Hash)]
+#[derive(
+    Default,
+    Debug,
+    PartialEq,
+    Eq,
+    Hash,
+    serde::Serialize,
+    serde::Deserialize
+)]

650-663: Unused private helper cloneReturn::_tokenize

_tokenize is only referenced once (inside tokenize_returns) and merely forwards to tokenize on each element. Inlining that call removes ~10 lines and another hop on the call stack for every invocation:

-    fn _tokenize(
-        &self,
-    ) -> <cloneCall as alloy_sol_types::SolCall>::ReturnToken<'_> {
-        (
-            <alloy::sol_types::sol_data::Address as alloy_sol_types::SolType>::tokenize(
-                &self._0,
-            ),
-            <alloy::sol_types::sol_data::Address as alloy_sol_types::SolType>::tokenize(
-                &self._1,
-            ),
-        )
-    }
+    // helper dropped – call site below expanded inline

and later

-    fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> {
-        cloneReturn::_tokenize(ret)
+    fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> {
+        (
+            <alloy::sol_types::sol_data::Address as alloy_sol_types::SolType>::tokenize(
+                &ret._0,
+            ),
+            <alloy::sol_types::sol_data::Address as alloy_sol_types::SolType>::tokenize(
+                &ret._1,
+            ),
+        )
     }

Removing the dead helper keeps the generated file slimmer without sacrificing clarity.


1582-1590: with_cloned_provider may incur an expensive deep clone

Cloning the provider blindly can be costly (e.g. cloning an HTTP client or signing middleware).
Consider constraining P to Clone + CheapClone (e.g. Arc) or documenting that providers should be lightweight clones. Alternatively, return Self holding Arc<P> to guarantee cheap reference counting.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed261f3 and 20b37c7.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • flake.lock is excluded by !**/*.lock
📒 Files selected for processing (29)
  • .github/workflows/check-bindings.yaml (1 hunks)
  • Cargo.toml (1 hunks)
  • chain/indexer/src/handlers.rs (1 hunks)
  • chain/rpc/src/client.rs (16 hunks)
  • chain/rpc/src/rpc.rs (11 hunks)
  • chain/types/src/lib.rs (2 hunks)
  • chain/types/src/utils.rs (10 hunks)
  • ethereum/bindings/Cargo.toml (1 hunks)
  • ethereum/bindings/src/codegen/hoprannouncements.rs (58 hunks)
  • ethereum/bindings/src/codegen/hoprannouncementsevents.rs (13 hunks)
  • ethereum/bindings/src/codegen/hoprchannelsevents.rs (31 hunks)
  • ethereum/bindings/src/codegen/hoprcrypto.rs (17 hunks)
  • ethereum/bindings/src/codegen/hoprdummyproxyfornetworkregistry.rs (50 hunks)
  • ethereum/bindings/src/codegen/hoprledger.rs (22 hunks)
  • ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (17 hunks)
  • ethereum/bindings/src/codegen/hoprnodesaferegistry.rs (64 hunks)
  • ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (13 hunks)
  • ethereum/bindings/src/codegen/hoprnodestakefactory.rs (32 hunks)
  • ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (12 hunks)
  • ethereum/bindings/src/codegen/hoprticketpriceoracle.rs (35 hunks)
  • ethereum/bindings/src/codegen/hoprticketpriceoracleevents.rs (11 hunks)
  • ethereum/bindings/src/codegen/hoprwinningprobabilityoracle.rs (42 hunks)
  • ethereum/bindings/src/codegen/hoprwinningprobabilityoracleevents.rs (14 hunks)
  • flake.nix (1 hunks)
  • hopli/src/environment_config.rs (2 hunks)
  • hopli/src/methods.rs (34 hunks)
  • hopli/src/win_prob.rs (1 hunks)
  • hopr/hopr-lib/tests/common/mod.rs (1 hunks)
  • justfile (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (6)
ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (13)
ethereum/bindings/src/codegen/hoprannouncementsevents.rs (13)
  • address (693-695)
  • provider (708-710)
  • new (156-164)
  • new (278-288)
  • new (397-402)
  • new (580-588)
  • new (656-665)
  • with_cloned_provider (715-721)
  • call_builder (733-738)
  • event_filter (750-754)
  • event_filter (759-759)
  • event_filter (763-763)
  • event_filter (769-769)
ethereum/bindings/src/codegen/hoprcrypto.rs (10)
  • address (596-598)
  • provider (611-613)
  • new (117-121)
  • new (190-194)
  • new (263-267)
  • new (488-496)
  • new (559-568)
  • with_cloned_provider (618-624)
  • call_builder (636-641)
  • event_filter (653-657)
ethereum/bindings/src/codegen/hoprchannelsevents.rs (23)
  • address (505-507)
  • address (1862-1864)
  • provider (520-522)
  • provider (1877-1879)
  • new (450-458)
  • new (493-502)
  • new (792-800)
  • new (910-918)
  • new (1026-1031)
  • new (1136-1144)
  • with_cloned_provider (527-533)
  • with_cloned_provider (1884-1890)
  • call_builder (545-550)
  • call_builder (1902-1907)
  • event_filter (562-566)
  • event_filter (1919-1923)
  • event_filter (1928-1928)
  • event_filter (1934-1934)
  • event_filter (1940-1940)
  • event_filter (1946-1946)
  • event_filter (1952-1952)
  • event_filter (1958-1958)
  • event_filter (1964-1964)
ethereum/bindings/src/codegen/hoprannouncements.rs (6)
  • address (3416-3418)
  • provider (3431-3433)
  • with_cloned_provider (3438-3444)
  • call_builder (3456-3461)
  • event_filter (3579-3583)
  • event_filter (3588-3588)
ethereum/bindings/src/codegen/hoprcapabilitypermissions.rs (4)
  • address (5297-5299)
  • provider (5312-5314)
  • with_cloned_provider (5319-5325)
  • call_builder (5337-5342)
ethereum/bindings/src/codegen/hoprledger.rs (4)
  • address (1028-1030)
  • provider (1043-1045)
  • with_cloned_provider (1050-1056)
  • call_builder (1068-1073)
ethereum/bindings/src/codegen/hoprdummyproxyfornetworkregistry.rs (4)
  • address (3434-3436)
  • provider (3449-3451)
  • with_cloned_provider (3456-3464)
  • call_builder (3476-3481)
ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (4)
  • address (1308-1310)
  • provider (1323-1325)
  • with_cloned_provider (1330-1336)
  • call_builder (1348-1353)
ethereum/bindings/src/codegen/hoprboost.rs (4)
  • address (8907-8909)
  • provider (8922-8924)
  • with_cloned_provider (8929-8935)
  • call_builder (8947-8952)
ethereum/bindings/src/codegen/hoprnodesaferegistry.rs (4)
  • address (3794-3796)
  • provider (3809-3811)
  • with_cloned_provider (3816-3822)
  • call_builder (3834-3839)
ethereum/bindings/src/codegen/hoprnetworkregistry.rs (4)
  • address (8986-8988)
  • provider (9001-9003)
  • with_cloned_provider (9008-9014)
  • call_builder (9026-9031)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (4)
  • address (679-681)
  • provider (694-696)
  • with_cloned_provider (701-707)
  • call_builder (719-724)
ethereum/bindings/src/codegen/hoprnodestakefactory.rs (9)
  • address (1563-1565)
  • provider (1578-1580)
  • clone (1126-1131)
  • clone (1177-1184)
  • clone (1610-1625)
  • with_cloned_provider (1585-1591)
  • call_builder (1603-1608)
  • NewHoprNodeStakeModule_filter (1662-1666)
  • NewHoprNodeStakeSafe_filter (1668-1672)
ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (8)
ethereum/bindings/src/codegen/hoprannouncementsevents.rs (9)
  • address (693-695)
  • provider (708-710)
  • new (156-164)
  • new (278-288)
  • new (397-402)
  • new (580-588)
  • new (656-665)
  • with_cloned_provider (715-721)
  • call_builder (733-738)
ethereum/bindings/src/codegen/hoprcrypto.rs (9)
  • address (596-598)
  • provider (611-613)
  • new (117-121)
  • new (190-194)
  • new (263-267)
  • new (488-496)
  • new (559-568)
  • with_cloned_provider (618-624)
  • call_builder (636-641)
ethereum/bindings/src/codegen/hoprledger.rs (4)
  • address (1028-1030)
  • provider (1043-1045)
  • with_cloned_provider (1050-1056)
  • call_builder (1068-1073)
ethereum/bindings/src/codegen/hoprnodesaferegistry.rs (4)
  • address (3794-3796)
  • provider (3809-3811)
  • with_cloned_provider (3816-3822)
  • call_builder (3834-3839)
ethereum/bindings/src/codegen/hoprnetworkregistry.rs (4)
  • address (8986-8988)
  • provider (9001-9003)
  • with_cloned_provider (9008-9014)
  • call_builder (9026-9031)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (4)
  • address (679-681)
  • provider (694-696)
  • with_cloned_provider (701-707)
  • call_builder (719-724)
ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (4)
  • address (513-515)
  • provider (528-530)
  • with_cloned_provider (535-541)
  • call_builder (553-558)
ethereum/bindings/src/codegen/hoprchannels.rs (8)
  • address (630-632)
  • address (13722-13724)
  • provider (645-647)
  • provider (13737-13739)
  • with_cloned_provider (652-658)
  • with_cloned_provider (13744-13750)
  • call_builder (670-675)
  • call_builder (13762-13767)
ethereum/bindings/src/codegen/hoprcrypto.rs (9)
ethereum/bindings/src/codegen/hoprchannels.rs (18)
  • InvalidCurvePoint (12635-12642)
  • InvalidCurvePoint (12906-12913)
  • InvalidFieldElement (12580-12587)
  • InvalidFieldElement (12851-12858)
  • InvalidPointWitness (12776-12783)
  • InvalidPointWitness (13051-13058)
  • selector (11229-11319)
  • selector (12467-12539)
  • address (630-632)
  • address (13722-13724)
  • provider (645-647)
  • provider (13737-13739)
  • fmt (604-606)
  • fmt (13647-13649)
  • with_cloned_provider (652-658)
  • with_cloned_provider (13744-13750)
  • call_builder (670-675)
  • call_builder (13762-13767)
ethereum/bindings/src/codegen/hoprcapabilitypermissions.rs (21)
  • abi_decode_raw_validate (767-772)
  • abi_decode_raw_validate (840-845)
  • abi_decode_raw_validate (913-918)
  • abi_decode_raw_validate (986-991)
  • abi_decode_raw_validate (1061-1066)
  • abi_decode_raw_validate (1134-1139)
  • abi_decode_raw_validate (1209-1214)
  • abi_decode_raw_validate (1284-1289)
  • abi_decode_raw_validate (1357-1362)
  • abi_decode_raw_validate (1430-1435)
  • selector (3890-3914)
  • selector (4290-4344)
  • address (5297-5299)
  • provider (5312-5314)
  • deploy (5199-5208)
  • deploy (5276-5282)
  • deploy_builder (5215-5220)
  • deploy_builder (5289-5294)
  • fmt (5244-5248)
  • with_cloned_provider (5319-5325)
  • call_builder (5337-5342)
ethereum/bindings/src/codegen/hoprledger.rs (10)
  • selector (672-684)
  • address (1028-1030)
  • provider (1043-1045)
  • deploy (935-944)
  • deploy (1007-1013)
  • deploy_builder (951-956)
  • deploy_builder (1020-1025)
  • fmt (977-979)
  • with_cloned_provider (1050-1056)
  • call_builder (1068-1073)
ethereum/bindings/src/codegen/hoprboost.rs (10)
  • selector (7442-7527)
  • address (8907-8909)
  • provider (8922-8924)
  • deploy (8792-8803)
  • deploy (8870-8878)
  • deploy_builder (8810-8819)
  • deploy_builder (8885-8904)
  • fmt (8840-8842)
  • with_cloned_provider (8929-8935)
  • call_builder (8947-8952)
ethereum/bindings/src/codegen/hoprnodesaferegistry.rs (7)
  • selector (2803-2834)
  • selector (3258-3282)
  • address (3794-3796)
  • provider (3809-3811)
  • fmt (3743-3745)
  • with_cloned_provider (3816-3822)
  • call_builder (3834-3839)
ethereum/bindings/src/codegen/hoprnodestakefactory.rs (10)
  • selector (1075-1085)
  • selector (1260-1266)
  • address (1563-1565)
  • provider (1578-1580)
  • fmt (1512-1514)
  • clone (1126-1131)
  • clone (1177-1184)
  • clone (1610-1625)
  • with_cloned_provider (1585-1591)
  • call_builder (1603-1608)
ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (9)
  • address (1308-1310)
  • provider (1323-1325)
  • deploy (1210-1219)
  • deploy (1287-1293)
  • deploy_builder (1226-1231)
  • deploy_builder (1300-1305)
  • fmt (1255-1259)
  • with_cloned_provider (1330-1336)
  • call_builder (1348-1353)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (5)
  • address (679-681)
  • provider (694-696)
  • fmt (626-630)
  • with_cloned_provider (701-707)
  • call_builder (719-724)
ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (5)
  • address (513-515)
  • provider (528-530)
  • fmt (460-464)
  • with_cloned_provider (535-541)
  • call_builder (553-558)
chain/types/src/utils.rs (5)
common/primitive-types/src/primitives.rs (1)
  • amount (207-209)
chain/api/src/executors.rs (1)
  • fund_channel (132-135)
chain/actions/src/payload.rs (3)
  • fund_channel (68-68)
  • fund_channel (199-220)
  • fund_channel (380-404)
chain/actions/src/channels.rs (2)
  • fund_channel (46-46)
  • fund_channel (122-162)
chain/rpc/src/client.rs (8)
  • provider (1001-1002)
  • provider (1031-1032)
  • provider (1077-1078)
  • provider (1113-1114)
  • provider (1167-1168)
  • provider (1221-1222)
  • provider (1277-1278)
  • provider (1333-1334)
ethereum/bindings/src/codegen/hoprnodesaferegistry.rs (1)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (8)
  • address (679-681)
  • provider (694-696)
  • fmt (626-630)
  • with_cloned_provider (701-707)
  • call_builder (719-724)
  • DergisteredNodeSafe_filter (742-746)
  • DomainSeparatorUpdated_filter (748-752)
  • RegisteredNodeSafe_filter (754-758)
ethereum/bindings/src/codegen/hoprwinningprobabilityoracle.rs (6)
ethereum/bindings/src/codegen/hoprwinningprobabilityoracleevents.rs (3)
  • from_underlying (115-119)
  • into_underlying (122-126)
  • WinProbUpdated_filter (573-577)
ethereum/bindings/src/codegen/hoprcrypto.rs (26)
  • from (97-99)
  • from (104-106)
  • from (170-172)
  • from (177-179)
  • from (243-245)
  • from (250-252)
  • abi_decode_raw_validate (127-132)
  • abi_decode_raw_validate (200-205)
  • abi_decode_raw_validate (273-278)
  • abi_decode_raw_validate (388-438)
  • new (117-121)
  • new (190-194)
  • new (263-267)
  • new (488-496)
  • new (559-568)
  • tokenize (123-125)
  • tokenize (196-198)
  • tokenize (269-271)
  • abi_decode_raw (335-385)
  • selector (312-324)
  • address (596-598)
  • provider (611-613)
  • fmt (545-547)
  • with_cloned_provider (618-624)
  • call_builder (636-641)
  • event_filter (653-657)
ethereum/bindings/src/codegen/hoprticketpriceoracle.rs (10)
  • renounceOwnership (1451-1458)
  • renounceOwnership (1524-1531)
  • renounceOwnership (2098-2102)
  • owner (1462-1467)
  • owner (1535-1542)
  • owner (2094-2096)
  • transferOwnership (1482-1489)
  • transferOwnership (1557-1564)
  • transferOwnership (2115-2120)
  • OwnershipTransferred_filter (2138-2142)
ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (5)
  • address (1308-1310)
  • provider (1323-1325)
  • fmt (1255-1259)
  • with_cloned_provider (1330-1336)
  • call_builder (1348-1353)
ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (5)
  • address (679-681)
  • provider (694-696)
  • fmt (626-630)
  • with_cloned_provider (701-707)
  • call_builder (719-724)
ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (5)
  • address (513-515)
  • provider (528-530)
  • fmt (460-464)
  • with_cloned_provider (535-541)
  • call_builder (553-558)
🔇 Additional comments (52)
ethereum/bindings/Cargo.toml (1)

12-12: Appropriate addition of serde derive feature

Adding the derive feature to serde is necessary to support the serialization and deserialization derives that have been added throughout the regenerated contract bindings in this Alloy v1 migration.

Cargo.toml (1)

50-50: Correct version update for alloy dependency

Updating to alloy 1.0.4 is essential for compatibility with Foundry's latest contract binding generation as mentioned in the PR objectives.

flake.nix (1)

12-12: Foundry version pin updated for Alloy v1 compatibility

This commit hash update for foundry.nix ensures compatibility with the upgraded Alloy v1.0.4 dependency.

.github/workflows/check-bindings.yaml (1)

52-53: Binding generation flags appropriately updated

The changes to binding generation flags align well with the Alloy v1 migration:

  1. Removing --skip-extra-derives allows the inclusion of serialization derives
  2. Adding --force ensures complete regeneration of all bindings
  3. Adding --skip-cargo-toml prevents automated changes to the manually updated Cargo.toml

These changes ensure consistent regeneration of contract bindings with the latest Alloy version.

hopli/src/win_prob.rs (1)

110-113: Simplified contract call return handling

The updated code properly adapts to Alloy v1's API changes by removing the tuple field access that was previously needed, while also improving error handling with a more descriptive message.

hopli/src/environment_config.rs (2)

156-156: Updated provider creation to use new Alloy v1 API

The provider builder now uses .connect_client(rpc_client) instead of .on_client(rpc_client) to match Alloy v1's updated API.


182-182: Updated provider creation to use new Alloy v1 API

The provider builder now uses .connect_client(rpc_client) instead of .on_client(rpc_client) to match Alloy v1's updated API.

chain/indexer/src/handlers.rs (8)

797-797: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


800-801: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


803-804: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


806-807: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


809-810: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


812-813: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


815-816: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.


818-819: Updated event decoding to match Alloy v1 API changes

The second boolean argument (validation flag) has been removed from decode_log method calls, as this parameter was removed in Alloy v1's API.

justfile (1)

5-6: Updated binding generation to specify Alloy v1.0.4

The binding generation command has been updated with new flags:

  • --force: Ensures regeneration, overriding any cache
  • --skip-cargo-toml: Avoids modifying Cargo.toml during binding generation
  • --alloy-version "1.0.4": Explicitly specifies the target Alloy version

These changes ensure consistent binding generation with the desired Alloy version.

hopr/hopr-lib/tests/common/mod.rs (1)

58-58: Updated provider creation to use new Alloy v1 API

The provider builder now uses .connect_client(rpc_client) instead of .on_client(rpc_client) to match Alloy v1's updated API.

chain/rpc/src/client.rs (1)

865-865: connect_client invocation looks good

The new ProviderBuilder::connect_client call compiles with Alloy v1 and returns the fully-built provider, so no extra .build() is required. Nothing else changed in the surrounding logic.

chain/types/src/lib.rs (2)

62-64: Removal of the phantom () generic is correct

Both proxy variants now carry only the provider generic, matching the regenerated bindings. No functional issues detected.


81-90: ContractInstances field-type update aligns with regenerated bindings

All fields now accept the simplified HoprXInstance<P> type. Constructor code below already passes provider.clone(), so nothing further is required.

chain/rpc/src/rpc.rs (1)

158-159: Updated builder chain is correct

ProviderBuilder::connect_client replaces the deprecated .on_client API and the filler chain is left untouched. Looks good.

ethereum/bindings/src/codegen/hoprchannelsevents.rs (1)

21-25: Consider marking the tuple-newtype as serde(transparent)

Balance, TicketIndex, and Timestamp are thin wrappers around primitive values, yet they are now serialised as one-element arrays ([123]) rather than the plain scalar (123).
If external JSON consumers expect the raw number, this silently breaks compatibility.

-#[derive(serde::Serialize, serde::Deserialize)]
-#[derive(Default, Debug, PartialEq, Eq, Hash)]
+#[derive(
+    Default,
+    Debug,
+    PartialEq,
+    Eq,
+    Hash,
+    serde::Serialize,
+    serde::Deserialize,
+)]
+#[serde(transparent)]

Adding #[serde(transparent)] (and repeating the change for TicketIndex and Timestamp) preserves the previous wire format while still giving you the derives.

Check any APIs or tests that serialise these types to confirm whether the new [value] shape is already relied upon.

ethereum/bindings/src/codegen/hoprnetworkregistryevents.rs (1)

1271-1280: Tiny improvement: keep the phantom field name consistent across bindings

Here the field is _network, in other generated modules older code used _network_transport.
While purely cosmetic, consistent naming avoids noisy diffs when the generator changes again.

No action needed if the generator is authoritative; just flagging in case manual edits creep in.

ethereum/bindings/src/codegen/hoprnodesaferegistryevents.rs (2)

486-531: Removal of the validate path changes run-time guarantees

decode_raw_log used to expose a validate flag that, when enabled, performed ABI-level validation of log data size.
With this change the public enum no longer offers a validating decoder; callers that relied on the stricter variant now silently lose that safety-net.

Two low-cost options:

  1. Re-introduce a decode_raw_log_validate companion that forwards to SolEvent::decode_raw_log_validate.
  2. Document in the module-level rust-doc that decode_raw_log performs no validation and that callers must call E::decode_raw_log_validate on the concrete event instead.

Failing to communicate this API break can lead to subtle production issues.


567-574: 👍 Generics simplification improves ergonomics

Great job removing the now-redundant transport generic – the new Provider<N> bound is clearer and drops a layer of noise throughout the API.

ethereum/bindings/src/codegen/hoprnodestakefactoryevents.rs (1)

301-308: Nice addition – serde derives on enums

Being able to serialise/deserialize the high-level event enums is very handy for off-chain pipelines.
👍

ethereum/bindings/src/codegen/hoprticketpriceoracleevents.rs (8)

64-65: Good addition of serialization support to event structs

Adding these derives enables JSON serialization/deserialization support for the event structures, which will be useful for logging, storage, and inter-process communication.


178-179: Consistent serialization support for event enum

Good to see the same serialization capabilities added to the event enum, maintaining consistency with the individual event structs.


255-262: Simplification of generic parameters

The removal of the transport type parameter T simplifies the API and aligns with Alloy v1's architecture changes where the provider interface now abstracts away transport details.


269-278: Simplified deploy function signature

The deploy function now has a cleaner signature while maintaining the same functionality, which improves readability and usability.


285-290: Streamlined deploy_builder implementation

The simplified generic bounds here match the other changes throughout the file, creating consistency across the API.


309-309: Updated phantom data field name

Renaming from _transport to _network more accurately represents what the phantom data is tracking after removing the transport generic parameter.


386-394: Simplified provider cloning implementation

The with_cloned_provider method has been updated to use the simplified type parameters while maintaining the same functionality.


399-403: Consistent trait bound updates across implementation blocks

The trait bounds have been updated across all implementation blocks to be consistent with the new type parameter structure in Alloy v1.

Also applies to: 416-428

chain/types/src/utils.rs (12)

69-72: Simplified function signature for mint_tokens

The function signature has been updated to remove the transport type parameter T, which aligns with Alloy v1's architecture changes and simplifies the API.


108-117: Updated function signature for fund_node

The simplification of generic bounds improves readability while maintaining the same functionality.


141-150: Simplified fund_channel function signature

Consistent with other changes, the transport generic parameter has been removed, aligning with Alloy v1's provider abstraction.


170-180: Updated fund_channel_from_different_client signature

The change maintains the pattern of simplifying generic bounds across all functions in the file.


181-183: Updated contract instance creation

Contract instance creation now uses simplified type parameters without the transport generic.


202-211: Simplified get_safe_tx function signature

The function now has a cleaner signature that focuses on the provider and network generics.


225-225: More idiomatic conversion using into()

Changed from accessing tuple field with ._0 to using the more idiomatic .into() method, which improves code readability.


230-230: Simplified type conversion for data hash

Using .into() directly for the data hash is more concise than previous implementation.


255-265: Updated include_node_to_module_by_safe signature

Consistent with other functions, the transport generic parameter has been removed.


295-305: Simplified add_announcement_as_target signature

The function signature has been updated to remove the transport type parameter, maintaining consistency with other changes.


331-341: Updated approve_channel_transfer_from_safe signature

The signature has been simplified to improve readability while maintaining the same functionality.


369-376: Simplified deploy_one_safe_one_module_and_setup_for_testing signature

The function signature has been updated to align with Alloy v1's provider abstraction.

ethereum/bindings/src/codegen/hoprdummyproxyfornetworkregistry.rs (3)

3304-3311: Generic parameter change – audit manual instantiations

Instance<P, N> replaced the previous Instance<P, T, N> signature. Any
hand-written code that still supplies three generics will fail to compile.

Search the code-base (tests, helpers, examples) for
HoprDummyProxyForNetworkRegistryInstance< to ensure all call-sites were
updated.

Also applies to: 3318-3328, 3335-3343


3368-3375: Privacy-aware Debug output looks good

The custom Debug impl prints only the contract address, avoiding accidental
exposure of provider URLs or credentials. No action required.

Also applies to: 3453-3464


299-301:

✅ Verification successful

serde derives added – verify crate features

Almost every struct/enum now has #[derive(Serialize, Deserialize)].
The Alloy crates expose these trait impls only when compiled with the
serde feature. If the workspace disables default features, the build will
fail with errors like “Serialize is not implemented for U256”.

Please confirm that Cargo.toml enables the feature, e.g.:

alloy-sol-types = { version = "1.0.4", features = ["serde"] }
alloy-primitives = { version = "1.0.4", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }

and that downstream crates propagate the feature.

Also applies to: 406-408, 514-515, 621-622, 805-807, 813-816, 954-956, 968-970, 1126-1129, 1261-1263, 1417-1419, 1559-1561, 1704-1706, 1858-1860, 2012-2014, 2159-2161, 2297-2299, 2443-2445, 3160-3162


I’ll check the workspace and the ethereum/bindings crate to confirm whether the serde feature is enabled for the Alloy dependencies.


🏁 Script executed:

#!/bin/bash

set -e

echo "=== Cargo.toml files ==="
find . -maxdepth 4 -type f -name Cargo.toml

echo
echo "=== Root Cargo.toml (first 200 lines) ==="
sed -n '1,200p' Cargo.toml

echo
echo "=== Root Cargo.toml: alloy-sol-types, alloy-primitives, serde deps ==="
grep -n -E 'alloy-sol-types|alloy-primitives|serde' Cargo.toml || echo "No matches in root Cargo.toml"

echo
echo "=== Locating ethereum/bindings Cargo.toml ==="
BINDING_CARGO_TOML=$(find . -path '*/ethereum/bindings/Cargo.toml' -maxdepth 5 2>/dev/null)
if [ -n "$BINDING_CARGO_TOML" ]; then
  echo "Found: $BINDING_CARGO_TOML"
  echo
  echo "=== ethereum/bindings Cargo.toml (first 200 lines) ==="
  sed -n '1,200p' "$BINDING_CARGO_TOML"
  echo
  echo "=== ethereum/bindings Cargo.toml: alloy-sol-types, alloy-primitives, serde deps ==="
  grep -n -E 'alloy-sol-types|alloy-primitives|serde' "$BINDING_CARGO_TOML" || echo "No matches in ethereum/bindings Cargo.toml"
else
  echo "No ethereum/bindings Cargo.toml found"
fi

Length of output: 9033


Serde feature check passed
Confirmed that ethereum/bindings/Cargo.toml includes

serde = { workspace = true, features = ["derive"] }

and that the root workspace enables primitive-types with its "serde" feature. All Serialize/Deserialize derives (including those on U256) will compile successfully. No further changes needed.

hopli/src/methods.rs (3)

207-207: Type parameter simplification looks good

The code has been properly updated to reflect Alloy v1 type simplifications by removing unused unit type parameters from contract instance types. The generic type parameters were consistently simplified across the entire file.

Also applies to: 306-307, 317-317, 369-370, 529-530, 553-554, 619-620, 649-650, 795-805, 1011-1012, 1033-1034, 1100-1101, 1143-1144, 1221-1223, 1281-1282


312-312: Return value handling updated correctly

Return values from multicall aggregate calls and contract method calls are now correctly handled by returning raw values directly rather than accessing tuple fields like ._0 or .balance. This aligns with the binding changes in Alloy v1 that simplified return types.

Also applies to: 335-336, 350-351, 410-412, 540-541, 1023-1024, 1240-1241, 1319-1320


1517-1517: Test assertions updated for Alloy v1 compatibility

The test assertions have been properly updated to work with the direct return values from contract calls, consistent with the changes in the main codebase. Boolean and numeric returns are now used directly without tuple field access.

Also applies to: 1579-1579, 1900-1901, 1907-1908, 1914-1914, 1919-1920, 2097-2098, 2143-2144, 2154-2155, 2219-2222, 2237-2240

@QYuQianchen QYuQianchen marked this pull request as draft May 21, 2025 15:45
@QYuQianchen QYuQianchen marked this pull request as ready for review May 21, 2025 17:43
@tolbrino tolbrino added this to the 3.0.0 milestone May 22, 2025
@tolbrino tolbrino removed this from hoprnet May 22, 2025
@QYuQianchen QYuQianchen added this pull request to the merge queue May 23, 2025
github-merge-queue bot pushed a commit that referenced this pull request May 23, 2025
Co-authored-by: Lukas <lukas.pohanka@inina.net>
Co-authored-by: Tino Breddin <tino@hoprnet.org>
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks May 23, 2025
@QYuQianchen QYuQianchen added this pull request to the merge queue May 23, 2025
Merged via the queue into master with commit fb9bc86 May 23, 2025
31 of 32 checks passed
@QYuQianchen QYuQianchen deleted the q/migrate-to-alloy-v1 branch May 23, 2025 11:05
tolbrino added a commit that referenced this pull request May 23, 2025
Co-authored-by: Lukas <lukas.pohanka@inina.net>
Co-authored-by: Tino Breddin <tino@hoprnet.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

alloy-rs must be updated to the most recent stable v1 version
3 participants