-
Notifications
You must be signed in to change notification settings - Fork 795
Ensure a consistent chain ID between a signer and provider in SignerMiddleware #1095
Conversation
Seems like the updated ganache behaves differently and caused the run to fail, the test probably needs to be updated:
|
839baa0
to
3bf49b5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @gakonst
ethers-middleware/src/signer.rs
Outdated
/// | ||
/// [`Middleware`] ethers_providers::Middleware | ||
/// [`Signer`] ethers_signers::Signer | ||
pub async fn new(inner: M, signer: S) -> Result<Self, SignerMiddlewareError<M, S>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is definitely an improvement but this breaks, and will be redundant if the user manually sets the chain id without requesting it from the inner middleware.
I'd rather like to make this a separate asynchronous function that does this. basically with_signer
ethers-middleware/tests/signer.rs
Outdated
let chain_id = provider.get_chainid().await.unwrap().as_u64(); | ||
let wallet = wallet.with_chain_id(chain_id); | ||
let provider = SignerMiddleware::new(provider, wallet); | ||
let provider = SignerMiddleware::new(provider, wallet).await.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here for example, in this scenario, we're now querying the chain id twice
I think moving to a new method instead of a breaking change makes sense here. Not sure what the best name for the function is, something that declares that it auto detects chain id ideally |
3bf49b5
to
9d21591
Compare
Just switched to a new method /// Creates a new client from the provider and signer.
/// Sets the address of this middleware to the address of the signer.
/// Sets the chain id of the signer to the chain id of the inner [`Middleware`] passed in,
/// using the [`Signer`]'s implementation of with_chain_id.
///
/// [`Middleware`] ethers_providers::Middleware
/// [`Signer`] ethers_signers::Signer
pub async fn new_with_provider_chain(
inner: M,
signer: S,
) -> Result<Self, SignerMiddlewareError<M, S>> {
let address = signer.address();
let chain_id =
inner.get_chainid().await.map_err(|e| SignerMiddlewareError::MiddlewareError(e))?;
let signer = signer.with_chain_id(chain_id.as_u64());
Ok(SignerMiddleware { inner, signer, address })
} Edited the comment on |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to remove the formatting change in the doc comments, otherwise lgtm
Require SignerMiddleware to fetch the inner middleware's to set for the signer. SignerMiddleware now requires an instantiated middleware with an accessible get_chainid method.
newer ganache version is needed to specify the ganache provider chain id in tests
* remove gas estimation equality assert in deploy_and_call_contract - updated version of ganache no longer returns the same value for gas estimation and gas_used
924acff
to
6fbff4c
Compare
Removed indents and rebased |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gg thx!
Motivation
Frequently users run into errors returned by a
Provider
that are caused by chain ID inconsistencies between the user'sSigner
andProvider
. For example, if the user tries to sign/send a transaction using aSignerMiddleware
instantiated with aSigner
andProvider
that have different chain IDs, they might get this error from the provider:Since users often use a
SignerMiddleware
to interact with both a provider and signer, it would be useful to ensure that theSigner
uses the same chain ID as theProvider
, to prevent this type of user error. Other approaches were discussed in a different issue.Solution
Update the
SignerMiddleware
constructor andwith_signer
method to set the passedSigner
's chain ID to the ID retrieved from the provider.This changes the following
SignerMiddleware
methods:Old:
New:
We also have removed the
#[must_use]
attribute fromwith_signer
, since it doesn't do anything for async functions.Importantly, if a
chain_id
cannot be retrieved from the provider (due to a provider error or some other reason), we bubble up the error.Previously, the implementation details of the provider were not relevant to the creation of a
SignerMiddleware
.Now, the
SignerMiddleware
must be constructed with a provider with an implemented and workingget_chainid
method, ornew
/with_signer
will return an error rather than a newSignerMiddleware
.Additionally, this breaks current uses of
SignerMiddleware
, since theResult
must be handled, and each method is nowasync
, since we're now interacting with a provider.Tests are added which set a custom chain ID for Ganache and make sure the signer properly pulls the custom chain ID. To set a chain ID on Ganache, it had to be updated. There may be some differences in behavior between the two versions, so we should watch for test failures after re-enabling the relevant section of CI.
PR Checklist