Skip to content

Commit a893553

Browse files
chore(e2e): only call map_account if account is not mapped yet (#2483)
* feat: if not mapped yet * chore: fix method name and add CHANGELOG * fix: clippy warnings * original_account_entry * chore: minor fixes * chore: add new error type * chore: Remove `skip_clippy_and_linting` from contract_build args See use-ink/cargo-contract#2015 --------- Co-authored-by: davidsemakula <[email protected]>
1 parent c479afa commit a893553

File tree

4 files changed

+58
-8
lines changed

4 files changed

+58
-8
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ You can find binary releases of the node [here](https://github.com/use-ink/ink-n
226226
## Fixed
227227
- [E2E] Have port parsing handle comma-separated list ‒ [#2336](https://github.com/use-ink/ink/pull/2336)
228228
- Always use ink! ABI/ SCALE codec for constructor and instantiation related builders and utilities - [#2474](https://github.com/use-ink/ink/pull/2474)
229+
- Get rid of "extrinsic for call failed: Pallet error: Revive::AccountAlreadyMapped" - [2483](https://github.com/use-ink/ink/pull/2483)
229230

230231
## Version 5.1.0
231232

crates/e2e/src/contract_build.rs

-1
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,6 @@ fn build_contract(
184184
keep_debug_symbols: false,
185185
extra_lints: false,
186186
output_type: OutputType::HumanReadable,
187-
skip_clippy_and_linting: false,
188187
image: ImageVariant::Default,
189188
metadata_spec: MetadataSpec::Ink,
190189
};

crates/e2e/src/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ pub enum Error<DispatchError: fmt::Debug + fmt::Display> {
3939
#[error("Call dry-run error: {0}")]
4040
CallDryRun(DryRunError<DispatchError>),
4141
/// The `call` extrinsic failed.
42-
/// The `call` extrinsic failed.
4342
#[error("Call extrinsic error: {0}")]
4443
CallExtrinsic(DispatchError),
4544
/// The `remove_code` extrinsic failed.
@@ -51,6 +50,9 @@ pub enum Error<DispatchError: fmt::Debug + fmt::Display> {
5150
/// Decoding failed.
5251
#[error("Decoding failed: {0}")]
5352
Decoding(String),
53+
/// Other error.
54+
#[error("Other error: {0}")]
55+
Other(String),
5456
}
5557

5658
/// Error during a dry run RPC invocation.

crates/e2e/src/subxt_client.rs

+54-6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ use crate::{
5151
ContractsBackend,
5252
E2EBackend,
5353
};
54+
use ink::H160;
5455
use ink_env::{
5556
call::{
5657
utils::{
@@ -73,7 +74,10 @@ use ink_primitives::{
7374
};
7475
use jsonrpsee::core::async_trait;
7576
use pallet_revive::evm::CallTrace;
76-
use scale::Encode;
77+
use scale::{
78+
Decode,
79+
Encode,
80+
};
7781
use sp_weights::Weight;
7882
#[cfg(feature = "std")]
7983
use std::fmt::Debug;
@@ -191,11 +195,7 @@ where
191195
}
192196
}
193197

194-
// copied from `pallet-revive`
195-
let account_id =
196-
<subxt_signer::sr25519::Keypair as subxt::tx::Signer<C>>::account_id(signer);
197-
let account_bytes = account_id.encode();
198-
let deployer = AccountIdMapper::to_address(account_bytes.as_ref());
198+
let deployer = self.derive_keypair_address(signer);
199199
let addr = pallet_revive::create2(
200200
&deployer,
201201
&code[..],
@@ -320,6 +320,50 @@ where
320320
pub fn url(&self) -> &str {
321321
&self.url
322322
}
323+
324+
/// Derives the Ethereum address from a keypair.
325+
// copied from `pallet-revive`
326+
fn derive_keypair_address(&self, signer: &Keypair) -> H160 {
327+
let account_id = <Keypair as subxt::tx::Signer<C>>::account_id(signer);
328+
let account_bytes = account_id.encode();
329+
AccountIdMapper::to_address(account_bytes.as_ref())
330+
}
331+
332+
/// Returns the original mapped `AccountId32` for a `H160`.
333+
async fn fetch_original_account(
334+
&self,
335+
addr: &H160,
336+
) -> Result<Option<C::AccountId>, Error> {
337+
let original_account_entry = subxt::dynamic::storage(
338+
"Revive",
339+
"OriginalAccount",
340+
vec![Value::from_bytes(addr)],
341+
);
342+
let best_block = self.api.best_block().await;
343+
let raw_value = self
344+
.api
345+
.client
346+
.storage()
347+
.at(best_block)
348+
.fetch(&original_account_entry)
349+
.await
350+
.map_err(|err| {
351+
Error::Other(format!("Unable to fetch original account: {err:?}"))
352+
})?;
353+
Ok(match raw_value {
354+
Some(value) => {
355+
let raw_account_id = value.as_type::<[u8; 32]>().map_err(|err| {
356+
Error::Decoding(format!("unable to deserialize AccountId: {}", err))
357+
})?;
358+
let account: C::AccountId = Decode::decode(&mut &raw_account_id[..])
359+
.map_err(|err| {
360+
Error::Decoding(format!("unable to decode AccountId: {}", err))
361+
})?;
362+
Some(account)
363+
}
364+
None => None,
365+
})
366+
}
323367
}
324368

325369
#[async_trait]
@@ -697,6 +741,10 @@ where
697741
}
698742

699743
async fn map_account(&mut self, caller: &Keypair) -> Result<(), Self::Error> {
744+
let addr = self.derive_keypair_address(caller);
745+
if self.fetch_original_account(&addr).await?.is_some() {
746+
return Ok(());
747+
}
700748
let tx_events = self.api.map_account(caller).await;
701749

702750
for evt in tx_events.iter() {

0 commit comments

Comments
 (0)