Skip to content

Commit

Permalink
Merge branch 'main' into n/fix-lpg-weights
Browse files Browse the repository at this point in the history
  • Loading branch information
NunoAlexandre authored Sep 11, 2023
2 parents 8f8f1cc + 0f907f3 commit adba08a
Show file tree
Hide file tree
Showing 17 changed files with 161 additions and 188 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.

185 changes: 32 additions & 153 deletions pallets/ethereum-transaction/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,12 @@
use cfg_primitives::TRANSACTION_RECOVERY_ID;
use cfg_traits::ethereum::EthereumTransactor;
use ethereum::{LegacyTransaction, TransactionAction, TransactionSignature, TransactionV2};
use fp_evm::CallOrCreateInfo;
use frame_support::{
dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo},
pallet_prelude::*,
};
pub use pallet::*;
use pallet_evm::{ExitError, ExitFatal, ExitReason};
use sp_core::{H160, H256, U256};
use sp_std::vec::Vec;

#[cfg(test)]
mod mock;
Expand All @@ -32,106 +29,46 @@ mod tests;

#[frame_support::pallet]
pub mod pallet {
use frame_system::pallet_prelude::OriginFor;

use super::*;

#[pallet::pallet]
#[pallet::generate_store(pub (super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config + pallet_ethereum::Config {
/// The event type.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
pub trait Config: frame_system::Config + pallet_ethereum::Config
where
OriginFor<Self>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<Self>>>,
{
}

/// Storage for nonce.
#[pallet::storage]
#[pallet::getter(fn nonce)]
pub(crate) type Nonce<T: Config> = StorageValue<_, U256, ValueQuery>;

#[pallet::event]
#[pallet::generate_deposit(pub (super) fn deposit_event)]
pub enum Event<T: Config> {
/// A call was executed.
Executed {
from: H160,
to: H160,
exit_reason: ExitReason,
value: Vec<u8>,
},
}

#[pallet::error]
pub enum Error<T> {
/// Trying to pop from an empty stack.
StackUnderflow,

/// Trying to push into a stack over stack limit.
StackOverflow,

/// Jump destination is invalid.
InvalidJump,

/// An opcode accesses memory region, but the region is invalid.
InvalidRange,

/// Encountered the designated invalid opcode.
DesignatedInvalid,

/// Call stack is too deep (runtime).
CallTooDeep,

/// Create opcode encountered collision (runtime).
CreateCollision,

/// Create init code exceeds limit (runtime).
CreateContractLimit,

/// Invalid opcode during execution or starting byte is 0xef. See [EIP-3541](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-3541.md).
InvalidCode(u8),

/// An opcode accesses external information, but the request is off
/// offset limit (runtime).
OutOfOffset,

/// Execution runs out of gas (runtime).
OutOfGas,

/// Not enough fund to start the execution (runtime).
OutOfFund,

/// PC underflowed (unused).
PCUnderflow,

/// Attempt to create an empty account (runtime, unused).
CreateEmpty,

/// The operation is not supported.
NotSupported,
/// The trap (interrupt) is unhandled.
UnhandledInterrupt,

/// Machine encountered an explicit revert.
Reverted,

/// Unexpected result when executing a transaction.
UnexpectedExecuteResult,

/// Other normal errors.
Other,
}

impl<T: Config> Pallet<T> {
fn get_transaction_signature() -> Option<TransactionSignature> {
//TODO(cdamian): Same signature as the one in ethereum-xcm.
impl<T: Config> Pallet<T>
where
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
pub fn get_transaction_signature() -> Option<TransactionSignature> {
TransactionSignature::new(
TRANSACTION_RECOVERY_ID,
H256::from_low_u64_be(1u64),
H256::from_low_u64_be(1u64),
H256::from_low_u64_be(2u64),
H256::from_low_u64_be(2u64),
)
}
}

impl<T: Config> EthereumTransactor for Pallet<T> {
impl<T: Config> EthereumTransactor for Pallet<T>
where
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
/// This implementation serves as a wrapper around the Ethereum pallet
/// execute functionality. It keeps track of the nonce used for each
/// call and builds a fake signature for executing the provided call.
Expand Down Expand Up @@ -170,10 +107,9 @@ pub mod pallet {

Nonce::<T>::put(nonce.saturating_add(U256::one()));

let (_target, _value, info) = pallet_ethereum::Pallet::<T>::execute(
from,
&transaction,
Some(T::config().clone()),
pallet_ethereum::Pallet::<T>::transact(
pallet_ethereum::Origin::EthereumTransaction(from).into(),
transaction,
)
.map_err(|e| {
let weight = e.post_info.actual_weight.map_or(Weight::zero(), |w| w);
Expand All @@ -185,72 +121,15 @@ pub mod pallet {
},
error: e.error,
}
})?;

let dispatch_info = PostDispatchInfo {
actual_weight: Some(read_weight),
})
.map(|dispatch_info| PostDispatchInfo {
pays_fee: Pays::Yes,
};

match info {
CallOrCreateInfo::Call(call_info) => {
Self::deposit_event(Event::Executed {
from,
to,
exit_reason: call_info.exit_reason.clone(),
value: call_info.value.clone(),
});

match call_info.exit_reason {
ExitReason::Succeed(_) => Ok(dispatch_info),
ExitReason::Error(e) => Err(DispatchErrorWithPostInfo {
post_info: dispatch_info,
error: map_evm_error::<T>(e).into(),
}),
ExitReason::Revert(_) => Err(DispatchErrorWithPostInfo {
post_info: dispatch_info,
error: Error::<T>::Reverted.into(),
}),
ExitReason::Fatal(e) => Err(DispatchErrorWithPostInfo {
post_info: dispatch_info,
error: map_evm_fatal_error::<T>(e).into(),
}),
}
}
CallOrCreateInfo::Create(_) => Err(DispatchErrorWithPostInfo {
post_info: dispatch_info,
error: Error::<T>::UnexpectedExecuteResult.into(),
}),
}
}
}

fn map_evm_error<T: Config>(e: ExitError) -> Error<T> {
match e {
ExitError::StackUnderflow => Error::StackUnderflow,
ExitError::StackOverflow => Error::StackOverflow,
ExitError::InvalidJump => Error::InvalidJump,
ExitError::InvalidRange => Error::InvalidRange,
ExitError::DesignatedInvalid => Error::DesignatedInvalid,
ExitError::CallTooDeep => Error::CallTooDeep,
ExitError::CreateCollision => Error::CreateCollision,
ExitError::CreateContractLimit => Error::CreateContractLimit,
ExitError::InvalidCode(opcode) => Error::InvalidCode(opcode.0),
ExitError::OutOfOffset => Error::OutOfOffset,
ExitError::OutOfGas => Error::OutOfGas,
ExitError::OutOfFund => Error::OutOfFund,
ExitError::PCUnderflow => Error::PCUnderflow,
ExitError::CreateEmpty => Error::CreateEmpty,
ExitError::Other(_) => Error::Other,
}
}

fn map_evm_fatal_error<T: Config>(e: ExitFatal) -> Error<T> {
match e {
ExitFatal::NotSupported => Error::NotSupported,
ExitFatal::UnhandledInterrupt => Error::UnhandledInterrupt,
ExitFatal::CallErrorAsFatal(e) => map_evm_error(e),
ExitFatal::Other(_) => Error::Other,
actual_weight: dispatch_info
.actual_weight
.map_or(Some(read_weight), |weight| {
Some(weight.saturating_add(read_weight))
}),
})
}
}
}
4 changes: 1 addition & 3 deletions pallets/ethereum-transaction/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,7 @@ impl pallet_ethereum::Config for Runtime {
type StateRoot = IntermediateStateRoot<Self>;
}

impl pallet_ethereum_transaction::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}
impl pallet_ethereum_transaction::Config for Runtime {}

pub fn new_test_ext() -> sp_io::TestExternalities {
let storage = frame_system::GenesisConfig::default()
Expand Down
13 changes: 9 additions & 4 deletions pallets/ethereum-transaction/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use pallet_evm::{AddressMapping, Error::BalanceLow};
use sp_core::{crypto::AccountId32, H160, U256};

use super::mock::*;
use crate::{pallet::Nonce, Error};
use crate::pallet::Nonce;

mod utils {
use super::*;
Expand Down Expand Up @@ -101,15 +101,20 @@ mod call {

assert_eq!(Nonce::<Runtime>::get(), U256::from(0));

let res = <EthereumTransaction as EthereumTransactor>::call(
// NOTE: We can not check for errors as the internal `pallet-ethereum` logic
// does not transform an EVM error into an Substrate error and return
// `Ok(..)` in theses cases.
//
// We can also not mimic the `pallet-ethereum::Pallet::<T>::transact(..)`
// code path as some needed parts are private.
assert_ok!(<EthereumTransaction as EthereumTransactor>::call(
sender,
to,
data.as_slice(),
value,
gas_price,
gas_limit,
);
assert_eq!(res.err().unwrap().error, Error::<Runtime>::OutOfGas.into());
));

assert_eq!(Nonce::<Runtime>::get(), U256::from(1));
});
Expand Down
9 changes: 9 additions & 0 deletions pallets/liquidity-pools-gateway/routers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use frame_support::{
ensure,
traits::OriginTrait,
};
use frame_system::pallet_prelude::OriginFor;
use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights};
use scale_info::TypeInfo;
use sp_core::{bounded::BoundedVec, ConstU32, H160, H256, U256};
Expand Down Expand Up @@ -84,6 +85,8 @@ where
+ pallet_ethereum_transaction::Config
+ pallet_evm::Config,
T::AccountId: AsRef<[u8; 32]>,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
EthereumXCM(EthereumXCMRouter<T>),
AxelarEVM(AxelarEVMRouter<T>),
Expand All @@ -98,6 +101,8 @@ where
+ pallet_ethereum_transaction::Config
+ pallet_evm::Config,
T::AccountId: AsRef<[u8; 32]>,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
type Message = MessageOf<T>;
type Sender = AccountIdOf<T>;
Expand All @@ -124,6 +129,8 @@ where
pub struct EVMRouter<T>
where
T: frame_system::Config + pallet_ethereum_transaction::Config + pallet_evm::Config,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
pub evm_domain: EVMDomain,
pub _marker: PhantomData<T>,
Expand All @@ -133,6 +140,8 @@ impl<T> EVMRouter<T>
where
T: frame_system::Config + pallet_ethereum_transaction::Config + pallet_evm::Config,
T::AccountId: AsRef<[u8; 32]>,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
/// Performs an extra check to ensure that the actual contract is deployed
/// at the provided address and that the contract code hash matches.
Expand Down
4 changes: 1 addition & 3 deletions pallets/liquidity-pools-gateway/routers/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ impl pallet_mock_liquidity_pools::Config for Runtime {
type Message = MessageMock;
}

impl pallet_ethereum_transaction::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
}
impl pallet_ethereum_transaction::Config for Runtime {}

impl pallet_mock_routers::Config for Runtime {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use cfg_traits::liquidity_pools::Codec;
use codec::{Decode, Encode, MaxEncodedLen};
use ethabi::{Contract, Function, Param, ParamType, Token};
use frame_support::dispatch::{DispatchError, DispatchResult};
use frame_system::pallet_prelude::OriginFor;
use scale_info::{
prelude::string::{String, ToString},
TypeInfo,
Expand All @@ -34,6 +35,8 @@ where
+ pallet_liquidity_pools_gateway::Config
+ pallet_ethereum_transaction::Config
+ pallet_evm::Config,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
pub router: EVMRouter<T>,
pub evm_chain: BoundedVec<u8, ConstU32<MAX_AXELAR_EVM_CHAIN_SIZE>>,
Expand All @@ -48,6 +51,8 @@ where
+ pallet_ethereum_transaction::Config
+ pallet_evm::Config,
T::AccountId: AsRef<[u8; 32]>,
OriginFor<T>:
From<pallet_ethereum::Origin> + Into<Result<pallet_ethereum::Origin, OriginFor<T>>>,
{
/// Calls the init function on the EVM router.
pub fn do_init(&self) -> DispatchResult {
Expand Down
Loading

0 comments on commit adba08a

Please sign in to comment.