-
Notifications
You must be signed in to change notification settings - Fork 154
Migrate remaining e2e test utilities to alloy primitives #4001
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| use { | ||
| ethcontract::{Account, H160, U256}, | ||
| alloy::primitives::{Address, U256}, | ||
| reqwest::Url, | ||
| serde_json::json, | ||
| std::fmt::Debug, | ||
|
|
@@ -36,13 +36,13 @@ impl<T: Transport> ForkedNodeApi<T> { | |
| )) | ||
| } | ||
|
|
||
| pub async fn impersonate(&self, address: &H160) -> Result<Account, web3::Error> { | ||
| pub async fn impersonate(&self, address: &Address) -> Result<(), web3::Error> { | ||
| let json_address = serde_json::json!(address); | ||
| self.transport | ||
| .execute("anvil_impersonateAccount", vec![json_address]) | ||
| .await?; | ||
|
|
||
| Ok(Account::Local(*address, None)) | ||
| Ok(()) | ||
| } | ||
|
|
||
| pub fn set_chain_id(&self, chain_id: u64) -> CallFuture<(), T::Out> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is unused, IMO we can remove this |
||
|
|
@@ -53,7 +53,7 @@ impl<T: Transport> ForkedNodeApi<T> { | |
| ) | ||
| } | ||
|
|
||
| pub fn set_balance(&self, address: &H160, balance: U256) -> CallFuture<(), T::Out> { | ||
| pub fn set_balance(&self, address: &Address, balance: U256) -> CallFuture<(), T::Out> { | ||
| let json_address = serde_json::json!(address); | ||
| let json_balance = serde_json::json!(format!("{:#032x}", balance)); | ||
|
Comment on lines
+56
to
58
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nerd nit: if you expand the macro you'll see that json! simply calls serde_json::to_value (at least for these two cases) But it also makes the value you pass, a reference, meaning address becomes a double reference (&&Address) Unlike other parts of the codebase, where address is immediately de-referenced turning it into a copy, here we can simply remove the macro (which usually hides more magic than in this case) use the expanded API and avoid a double reference For the second call, we could do I know this is not directly related to the migration, but a migration is the perfect opportunity to improve the codebase like this |
||
| CallFuture::new( | ||
|
|
||
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.
The side effect of anvil_impersonateAccount still happens
And since this return values wasn't actually being used where this function was called, I changed this to return unit type (also specified in PR description).
I could use some feedback on what should be the equivalent return type in alloyrs for ethcontract::Account, especially if the value isn't being used.
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.
I think there are mostly 2 options:
impersonate()returns an alloy provider that doesn't have any signers (like here)ForkedNodeApihas aimpersonating_provider()that you are supposed to use for any number of different impersonated account.I think I prefer
2because it's pretty easy to communicate the correct way to use the API with doc comments.Ultimately both versions are not optimal because you can set
tx.fromarbitrarily so nothing on the type level stops you from impersonating some account and then using any other impersonation incompatible provider to send transactions for that account.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.
You can use
stop_impersonating_account— https://docs.rs/alloy-provider/latest/alloy_provider/ext/trait.AnvilApi.html#tymethod.anvil_stop_impersonating_accountThe reason we need an empty wallet is that if the wallet has at least one signer, it will have a default signer, meaning all TXs will be signed using it. The alternative is to send the TX "manually" as in, outside the regular alloy pipeline that fills in gaps for the TX (like nonce, signature, etc)
Personally, I don't think the current state API is great, a better way of solving this would be having the impersonate taking an async future/closure that executes within a scope of impersonation:
Kinda like:
And inside, what really happens is:
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.
Or, better yet, remove this whole API and just use what anvil already provides: https://docs.rs/alloy-provider/latest/alloy_provider/ext/trait.AnvilApi.html#tymethod.anvil_send_impersonated_transaction_with_config
Maybe you can make it more ergonomic
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.
Looking into this I opened #4004
Removed the forked node altogether, used alloy/anvil instead, no need to argue about the right return type :P