From 9e559aefeb0073cf77c6348311706e5bd6c7f300 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 13 Jan 2023 18:18:17 +0000 Subject: [PATCH] fix(abigen): ensure correct ABI in `From` impl (#2036) * fix(abigen): ensure correct ABI in `From` impl `new` creates a `Contract` with the correct ABI, but the `From` impl simply wraps the source `Contract`, which could have a completely different ABI. In effect this was an unsafe cast, and indeed was observed to trigger a "method not found (this should never happen)" panic for subsequent method lookups. Implementing `From` in terms of `new` fixes this, at the cost of an extra `Arc::clone()` (which I can't see how to eliminate without piercing the `ethers::contract::Contract` public API). * Remove unnecessary `async` from test Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- .../ethers-contract-abigen/src/contract.rs | 4 ++-- ethers-contract/tests/it/abigen.rs | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ethers-contract/ethers-contract-abigen/src/contract.rs b/ethers-contract/ethers-contract-abigen/src/contract.rs index dd34a4b3..371861be 100644 --- a/ethers-contract/ethers-contract-abigen/src/contract.rs +++ b/ethers-contract/ethers-contract-abigen/src/contract.rs @@ -150,7 +150,7 @@ impl Context { /// client at the given `Address`. The contract derefs to a `ethers::Contract` /// object pub fn new>(address: T, client: ::std::sync::Arc) -> Self { - #ethers_contract::Contract::new(address.into(), #abi_name.clone(), client).into() + Self(#ethers_contract::Contract::new(address.into(), #abi_name.clone(), client)) } #deployment_methods @@ -163,7 +163,7 @@ impl Context { impl From<#ethers_contract::Contract> for #name { fn from(contract: #ethers_contract::Contract) -> Self { - Self(contract) + Self::new(contract.address(), contract.client()) } } }; diff --git a/ethers-contract/tests/it/abigen.rs b/ethers-contract/tests/it/abigen.rs index 41706d01..0dacb25b 100644 --- a/ethers-contract/tests/it/abigen.rs +++ b/ethers-contract/tests/it/abigen.rs @@ -750,3 +750,21 @@ fn can_handle_overloaded_function_with_array() { ]"#, ); } + +#[test] +fn convert_uses_correct_abi() { + abigen!( + Foo, r#"[function foo()]"#; + Bar, r#"[function bar()]"#; + ); + + let provider = Arc::new(Provider::new(MockProvider::new())); + let foo = Foo::new(Address::default(), Arc::clone(&provider)); + + let contract: ðers_contract::Contract<_> = &foo; + let bar: Bar> = contract.clone().into(); + + // Ensure that `bar` is using the `Bar` ABI internally (this method lookup will panic if `bar` + // is incorrectly using the `Foo` ABI internally). + bar.bar().call(); +}