Skip to content

Commit

Permalink
Handle migration failed on EVM side (#1584)
Browse files Browse the repository at this point in the history
  • Loading branch information
AurevoirXavier authored Aug 28, 2024
1 parent c7ebe05 commit 4160e9f
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 50 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions pallet/deposit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ darwinia-staking-traits = { workspace = true }
dc-inflation = { workspace = true }
dc-types = { workspace = true }

# frontier
fp-evm = { workspace = true }

# polkadot-sdk
frame-support = { workspace = true }
frame-system = { workspace = true }
Expand Down Expand Up @@ -49,6 +52,9 @@ std = [
"darwinia-staking-traits/std",
"dc-inflation/std",

# frontier
"fp-evm/std",

# polkadot-sdk
"frame-support/std",
"frame-system/std",
Expand Down
40 changes: 28 additions & 12 deletions pallet/deposit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ use ethabi::{Function, Param, ParamType, StateMutability, Token};
// darwinia
use dc_inflation::MILLISECS_PER_YEAR;
use dc_types::{Balance, Moment};
// frontier
use fp_evm::{CallOrCreateInfo, ExitReason};
// polkadot-sdk
use frame_support::{
pallet_prelude::*,
Expand Down Expand Up @@ -136,6 +138,10 @@ pub mod pallet {
DepositNotInUse,
/// Deposit is already expired.
DepositAlreadyExpired,
/// Invalid deposit contract.
InvalidDepositContract,
/// Migration interaction with deposit contract failed.
MigrationFailedOnContract,
}

/// All deposits.
Expand Down Expand Up @@ -335,7 +341,7 @@ pub mod pallet {

T::Ring::transfer(&account_id(), &who, to_claim.0, AllowDeath)?;
T::Ring::transfer(&account_id(), &T::Treasury::get(), to_migrate.0, AllowDeath)?;
T::DepositMigrator::migrate(who.clone(), to_migrate.0, to_migrate.2);
T::DepositMigrator::migrate(who.clone(), to_migrate.0, to_migrate.2)?;

Self::deposit_event(Event::DepositsClaimed {
owner: who.clone(),
Expand Down Expand Up @@ -458,7 +464,9 @@ where
T: Config,
{
/// Migrate to contract.
fn migrate(_: T::AccountId, _: Balance, _: Vec<(Balance, Moment, Moment)>) {}
fn migrate(_: T::AccountId, _: Balance, _: Vec<(Balance, Moment, Moment)>) -> DispatchResult {
Ok(())
}
}
impl<T> MigrateToContract<T> for () where T: Config {}

Expand All @@ -484,16 +492,14 @@ where
T: Config + darwinia_ethtx_forwarder::Config,
T::AccountId: Into<H160>,
{
fn migrate(who: T::AccountId, total: Balance, deposits: Vec<(Balance, Moment, Moment)>) {
let Some(dc) = <DepositContract<T>>::get() else {
log::error!("deposit contract must be some; qed");

return;
};
let dc = dc.into();

fn migrate(
who: T::AccountId,
total: Balance,
deposits: Vec<(Balance, Moment, Moment)>,
) -> DispatchResult {
let dc = <DepositContract<T>>::get().ok_or(<Error<T>>::InvalidDepositContract)?.into();
#[allow(deprecated)]
darwinia_ethtx_forwarder::quick_forward_transact::<T>(
let exit_reason = match darwinia_ethtx_forwarder::quick_forward_transact::<T>(
T::Treasury::get().into(),
Function {
name: "migrate".into(),
Expand Down Expand Up @@ -535,7 +541,17 @@ where
dc,
total.into(),
1_000_000.into(),
)
)?
.1
{
CallOrCreateInfo::Call(i) => i.exit_reason,
CallOrCreateInfo::Create(i) => i.exit_reason,
};

match exit_reason {
ExitReason::Succeed(_) => Ok(()),
_ => Err(<Error<T>>::MigrationFailedOnContract)?,
}
}
}

Expand Down
84 changes: 50 additions & 34 deletions pallet/ethtx-forwarder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@ use ethereum::{
use scale_info::TypeInfo;
// frontier
use fp_ethereum::{TransactionData, ValidatedTransaction};
use fp_evm::{CheckEvmTransaction, CheckEvmTransactionConfig, TransactionValidationError};
use fp_evm::{
CallOrCreateInfo, CheckEvmTransaction, CheckEvmTransactionConfig, TransactionValidationError,
};
use pallet_evm::{FeeCalculator, GasWeightMapping, Runner};
// polkadot-sdk
use frame_support::{dispatch::DispatchResultWithPostInfo, traits::EnsureOrigin, PalletError};
use frame_support::{
dispatch::{DispatchErrorWithPostInfo, DispatchResultWithPostInfo, PostDispatchInfo},
traits::EnsureOrigin,
PalletError,
};
use sp_core::{Get, H160, H256, U256};
use sp_runtime::{
traits::{BadOrigin, UniqueSaturatedInto},
Expand Down Expand Up @@ -121,7 +127,7 @@ pub mod pallet {
origin: OriginFor<T>,
request: ForwardRequest,
) -> DispatchResultWithPostInfo {
Self::forward_transact_inner(ensure_forward_transact(origin)?, request)
Self::forward_transact_inner(ensure_forward_transact(origin)?, request).map(|(r, _)| r)
}
}
}
Expand Down Expand Up @@ -150,19 +156,19 @@ impl<T: Config> Pallet<T> {
None,
<T as pallet_evm::Config>::config(),
)
.map_err(|err| err.error.into())
.map_err(|e| e.error.into())
}

pub fn forward_transact_inner(
source: H160,
request: ForwardRequest,
) -> DispatchResultWithPostInfo {
) -> Result<(PostDispatchInfo, CallOrCreateInfo), DispatchErrorWithPostInfo> {
let transaction = Self::validated_transaction(source, request)?;

#[cfg(feature = "evm-tracing")]
return Self::trace_tx(source, transaction);
#[cfg(not(feature = "evm-tracing"))]
return T::ValidatedTransaction::apply(source, transaction).map(|(post_info, _)| post_info);
return T::ValidatedTransaction::apply(source, transaction);
}

fn validated_transaction(
Expand Down Expand Up @@ -280,51 +286,65 @@ impl<T: Config> Pallet<T> {
}

#[cfg(feature = "evm-tracing")]
fn trace_tx(source: H160, transaction: Transaction) -> DispatchResultWithPostInfo {
fn trace_tx(
source: H160,
transaction: Transaction,
) -> Result<(PostDispatchInfo, CallOrCreateInfo), DispatchErrorWithPostInfo> {
// frontier
use fp_evm::{CallInfo, ExitSucceed, UsedGas};
// moonbeam
use moonbeam_evm_tracer::tracer::EvmTracer;
// polkadot-sdk
use frame_support::{dispatch::PostDispatchInfo, storage::unhashed};
use frame_support::storage::unhashed;
use xcm_primitives::{EthereumXcmTracingStatus, ETHEREUM_XCM_TRACING_STORAGE_KEY};

let default_r = || {
Ok((
().into(),
CallOrCreateInfo::Call(CallInfo {
exit_reason: ExitSucceed::Returned.into(),
value: Default::default(),
used_gas: UsedGas {
standard: Default::default(),
effective: Default::default(),
},
weight_info: Default::default(),
logs: Default::default(),
}),
))
};

match unhashed::get(ETHEREUM_XCM_TRACING_STORAGE_KEY) {
Some(EthereumXcmTracingStatus::Block) => {
EvmTracer::emit_new();

let mut res = Ok(PostDispatchInfo::default());
let mut r = default_r();

EvmTracer::new().trace(|| {
res = T::ValidatedTransaction::apply(source, transaction)
.map(|(post_info, _)| post_info);
r = T::ValidatedTransaction::apply(source, transaction);
});

res
r
},
Some(EthereumXcmTracingStatus::Transaction(traced_transaction_hash)) => {
if transaction.hash() == traced_transaction_hash {
let mut res = Ok(PostDispatchInfo::default());
let mut r = default_r();

EvmTracer::new().trace(|| {
res = T::ValidatedTransaction::apply(source, transaction)
.map(|(post_info, _)| post_info);
r = T::ValidatedTransaction::apply(source, transaction);
});
unhashed::put::<EthereumXcmTracingStatus>(
ETHEREUM_XCM_TRACING_STORAGE_KEY,
&EthereumXcmTracingStatus::TransactionExited,
);

res
r
} else {
T::ValidatedTransaction::apply(source, transaction)
.map(|(post_info, _)| post_info)
}
},
Some(EthereumXcmTracingStatus::TransactionExited) => Ok(PostDispatchInfo {
actual_weight: None,
pays_fee: frame_support::pallet_prelude::Pays::No,
}),
None =>
T::ValidatedTransaction::apply(source, transaction).map(|(post_info, _)| post_info),
Some(EthereumXcmTracingStatus::TransactionExited) => default_r(),
None => T::ValidatedTransaction::apply(source, transaction),
}
}
}
Expand Down Expand Up @@ -386,19 +406,17 @@ pub fn quick_forward_transact<T>(
call: H160,
value: U256,
gas_limit: U256,
) where
) -> Result<(PostDispatchInfo, CallOrCreateInfo), DispatchError>
where
T: Config,
{
log::info!("forwarding {function:?} to {call:?} with {{ input: {input:?}, value: {value:?} }}");

let input = match function.encode_input(input) {
Ok(i) => i,
Err(e) => {
log::error!("failed to encode input due to {e:?}");
let input = function.encode_input(input).map_err(|e| {
log::error!("failed to encode input due to {e:?}");

return;
},
};
DispatchError::from("failed to encode input")
})?;
let req = ForwardRequest {
tx_type: TxType::LegacyTransaction,
action: TransactionAction::Call(call),
Expand All @@ -407,7 +425,5 @@ pub fn quick_forward_transact<T>(
gas_limit,
};

if let Err(e) = <Pallet<T>>::forward_transact_inner(source, req) {
log::error!("failed to forward ethtx due to {e:?}");
}
<Pallet<T>>::forward_transact_inner(source, req).map_err(|e| e.error)
}
12 changes: 8 additions & 4 deletions pallet/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1283,7 +1283,7 @@ where
let rsc = rsc.into();

#[allow(deprecated)]
darwinia_ethtx_forwarder::quick_forward_transact::<T>(
if let Err(e) = darwinia_ethtx_forwarder::quick_forward_transact::<T>(
<T as Config>::Treasury::get().into(),
Function {
name: "distributeReward".into(),
Expand All @@ -1300,7 +1300,9 @@ where
rsc,
amount.into(),
1_000_000.into(),
);
) {
log::error!("failed to forward call due to {e:?}");
}
}
}

Expand All @@ -1323,7 +1325,7 @@ where
let ksc = ksc.into();

#[allow(deprecated)]
darwinia_ethtx_forwarder::quick_forward_transact::<T>(
if let Err(e) = darwinia_ethtx_forwarder::quick_forward_transact::<T>(
<T as Config>::Treasury::get().into(),
Function {
name: "distributeRewards".into(),
Expand All @@ -1340,7 +1342,9 @@ where
ksc,
amount.into(),
1_000_000.into(),
);
) {
log::error!("failed to forward call due to {e:?}");
}
}
}

Expand Down

0 comments on commit 4160e9f

Please sign in to comment.