Skip to content

Ethers to Alloy Migration Guide

Rindexer released a breaking change for all Rust projects, which internally migrates from ethers to alloy.

This means that exposed types and primitives are now from Alloy rather than Ethers-rs; some methods have also been deprecated and this will require breaking changes to be implemented within any rindexer rust project.

The simple steps to take are as follows:

  1. Add alloy to your Cargo.toml
  2. Run rindexer codegen typings to get the latest codegen state
  3. Change all parameter names and types
  4. Change advanced methods

You can see more details on each section below.

1. Add alloy to your Cargo.toml

First you should add alloy to your Cargo.toml and delete ethers. You can now remove any references to the ethers crate and replace this will the newer alloy crate. It should be pegged to the same version used by rindexer internally to ensure type compatibility.

Replace in Cargo.toml

- ethers = "2.0.14"
+ alloy = { version = "0.15.6", features = ["full"] }

Then any references to ethers types in your own code can be replaced with the alloy types. You can read more in the migration docs.

- use ethers::prelude::U256;
+ use alloy::primitives::U256;

2. Run rindexer codegen typings to get the latest codegen state

Once you have added the alloy crate and changed any of your project-specific code uses you can now run the rindexer codegen with rindexer codegen typings. This will regenerate the bindings with alloy code and types.

If for some reason there are errors in your codegen file, please try deleting it before re-running. Otherwise raise an issue on github: https://github.com/joshstevens19/rindexer/issues.

This should lead to working error-free code in the codegen directory. At this point you should expect to errors in most of the actual custom indexing files if you have specified them. This is mainly due to the reasons below (parameter name changes & type changes).

3. Change all parameter names and types

You must now go through and deal with the errors in your specific handler functions. These will almost exclusively be related to casing changes i.e. token_id -> tokenId. Or it will be a type's name change, i.e H256 -> B256.

This should be relatively self explanatory, you can read more details below but it's just a simple manual process.

Solidity contract parameters

The casing of solidity contract parameters is now transparent, meaning the prior snake_case conversion will no longer be retained and instead you will be required to access an event parameter by it's source name.

This will typically be camelCase or occasionally UPPERCASE, the rust compiler will help with this and the conversion should be relatively simple, albeit it a manual process.

- EthereumSqlTypeWrapper::AddressBytes(t.event_data.on_behalf_of),
+ EthereumSqlTypeWrapper::AddressBytes(t.event_data.onBehalfOf),
Solidity types

The core EthereumSqlTypeWrapper have been ported to use the new alloy primitives internally, so if you are manually passing any ethers types such as the Address derived manually (i.e. not as an automatically exposed type from rindexer) then you will need ensure this is migrated to the new types.

Most simple types can be found in the alloy migration guide: https://alloy.rs/migrating-from-ethers/reference/

The most common types which experiences the rename are the Hash types, renamed to Byte types:

  • H256 -> B256
  • H128 -> B128
  • H256 -> B256
  • H512 -> B512

The above includes all Vec, and Byte representation variants e.g. VecB512, etc.

The following types have been retained but should be consisted deprecated and may be removed:

  • H160 -> Use Address types instead (Including all Vec, and Byte representation variants)

A simple find and replace should handle most of these cases

4. Change advanced methods

Most projects will by default use the underlying type, this is for when manual type manipulation is needed.

The final step may be to replace any methods that are erroring out, that previously were not. The most common of this will be the existence of as_u[BITS].

These methods are no longer exposed directly on all solidity primitive uint types. For example the as_u32() method which existed on a U256 is no longer directly accessible.

Instead now, if you wish to downcast, you can use the TryInto trait on most uint types to achieve the same outcome and handle errors gracefully in the event of an overflow (where before a panic would occur implicitly).

- EthereumSqlTypeWrapper::U32(t.tx_information.log_index.as_u32()),
+ EthereumSqlTypeWrapper::U32(t.tx_information.log_index.try_into().expect("log_index should fit in u32")),

You may also opt to match the underlying type

- EthereumSqlTypeWrapper::U32(t.tx_information.log_index.as_u32()),
+ EthereumSqlTypeWrapper::U256(t.tx_information.log_index),