Skip to content

Commit

Permalink
Merge branch 'main' into lp-v2/freeze-extrinsics
Browse files Browse the repository at this point in the history
  • Loading branch information
wischli authored Aug 9, 2024
2 parents c87eba6 + 1cb9fe3 commit ce1133c
Show file tree
Hide file tree
Showing 21 changed files with 44 additions and 2,027 deletions.
9 changes: 0 additions & 9 deletions Cargo.lock

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

5 changes: 0 additions & 5 deletions pallets/liquidity-pools-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ cfg-utils = { workspace = true }

[dev-dependencies]
cfg-mocks = { workspace = true, default-features = true }
cfg-primitives = { workspace = true, default-features = true }
hex-literal = { workspace = true }
pallet-balances = { workspace = true, default-features = true }
rand = { workspace = true, default-features = true }
runtime-common = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }

[features]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@ use fp_evm::{ExitError, PrecompileFailure, PrecompileHandle};
use frame_support::ensure;
use precompile_utils::prelude::*;
use sp_core::{bounded::BoundedVec, ConstU32, H256, U256};
use sp_runtime::{
traits::{BlakeTwo256, Hash},
DispatchError,
};
use sp_std::vec::Vec;
use sp_runtime::traits::{BlakeTwo256, Hash};

pub use crate::weights::WeightInfo;

Expand Down Expand Up @@ -203,21 +199,6 @@ pub mod pallet {
}
}

impl<T: Config> cfg_traits::TryConvert<(Vec<u8>, Vec<u8>), DomainAddress> for Pallet<T> {
type Error = DispatchError;

fn try_convert(origin: (Vec<u8>, Vec<u8>)) -> Result<DomainAddress, DispatchError> {
let (source_chain, source_address) = origin;

let domain_converter = SourceConversion::<T>::get(BlakeTwo256::hash(&source_chain))
.ok_or(Error::<T>::NoConverterForSource)?;

domain_converter
.try_convert(&source_address)
.ok_or(Error::<T>::AccountBytesMismatchForDomain.into())
}
}

#[precompile_utils::precompile]
impl<T: Config> Pallet<T>
where
Expand Down Expand Up @@ -287,16 +268,13 @@ where
exit_status: ExitError::Other("account bytes mismatch for domain".into()),
})?;

match pallet_liquidity_pools_gateway::Pallet::<T>::receive_message(
pallet_liquidity_pools_gateway::Pallet::<T>::receive_message(
pallet_liquidity_pools_gateway::GatewayOrigin::Domain(domain_address).into(),
msg,
)
.map(|_| ())
.map_err(TryDispatchError::Substrate)
{
Err(e) => Err(e.into()),
Ok(()) => Ok(()),
}
.map_err(Into::into)
}

// Mimics:
Expand Down
15 changes: 0 additions & 15 deletions pallets/liquidity-pools-gateway/routers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,6 @@ sp-std = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }

# XCM
pallet-xcm-transactor = { workspace = true }
staging-xcm = { workspace = true }
xcm-primitives = { workspace = true }

# EVM
ethabi = { workspace = true }
pallet-ethereum = { workspace = true }
Expand All @@ -44,9 +39,6 @@ lazy_static = { workspace = true }

cumulus-primitives-core = { workspace = true, default-features = true }

staging-xcm-builder = { workspace = true, default-features = true }
staging-xcm-executor = { workspace = true, default-features = true }

pallet-evm-chain-id = { workspace = true, default-features = true }
pallet-evm-precompile-simple = { workspace = true, default-features = true }
pallet-timestamp = { workspace = true, default-features = true }
Expand All @@ -71,11 +63,8 @@ std = [
"frame-system/std",
"sp-std/std",
"sp-core/std",
"staging-xcm/std",
"pallet-xcm-transactor/std",
"pallet-ethereum/std",
"pallet-ethereum-transaction/std",
"xcm-primitives/std",
"ethabi/std",
"scale-info/std",
"pallet-evm/std",
Expand All @@ -90,12 +79,9 @@ runtime-benchmarks = [
"frame-system/runtime-benchmarks",
"pallet-ethereum/runtime-benchmarks",
"pallet-ethereum-transaction/runtime-benchmarks",
"pallet-xcm-transactor/runtime-benchmarks",
"xcm-primitives/runtime-benchmarks",
"pallet-evm/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"staging-xcm-builder/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
Expand All @@ -106,7 +92,6 @@ try-runtime = [
"cfg-mocks/try-runtime",
"pallet-ethereum/try-runtime",
"pallet-ethereum-transaction/try-runtime",
"pallet-xcm-transactor/try-runtime",
"pallet-evm/try-runtime",
"pallet-balances/try-runtime",
"sp-runtime/try-runtime",
Expand Down
168 changes: 5 additions & 163 deletions pallets/liquidity-pools-gateway/routers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,17 @@
//! Moonbeam - via XCM.
#![cfg_attr(not(feature = "std"), no_std)]

// polkadot/blob/19f6665a6162e68cd2651f5fe3615d6676821f90/xcm/src/v3/mod.rs#
// L1193 Defensively we increase this value to allow UMP fragments through
// xcm-transactor to prepare our runtime for a relay upgrade where the xcm
// instruction weights are not ZERO hardcoded. If that happens stuff will break
// in our side. Rationale behind the value: e.g. staking unbond will go above
// 64kb and thus required_weight_at_most must be below overall weight but still
// above whatever value we decide to set. For this reason we set here a value
// that makes sense for the overall weight.
pub const DEFAULT_PROOF_SIZE: u64 = 256 * 1024;

// See moonbeam docs: https://docs.moonbeam.network/builders/interoperability/xcm/fees/#:~:text=As%20previously%20mentioned%2C%20Polkadot%20currently,1%2C000%2C000%2C000%20weight%20units%20per%20instruction
pub const XCM_INSTRUCTION_WEIGHT: u64 = 1_000_000_000;

/// Multiplier for converting a unit of gas into a unit of Substrate weight
pub const GAS_TO_WEIGHT_MULTIPLIER: u64 = 25_000;

use cfg_traits::{ethereum::EthereumTransactor, liquidity_pools::Router};
use frame_support::{
dispatch::PostDispatchInfo,
ensure,
pallet_prelude::{DispatchError, DispatchResult, DispatchResultWithPostInfo},
traits::OriginTrait,
weights::Weight,
};
use frame_system::pallet_prelude::OriginFor;
use pallet_xcm_transactor::{Currency, CurrencyPayment, TransactWeights};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::{bounded::BoundedVec, ConstU32, H160, H256, U256};
use sp_core::{H160, H256, U256};
use sp_runtime::traits::{BlakeTwo256, Hash};
use sp_std::{boxed::Box, marker::PhantomData, vec::Vec};
use staging_xcm::{latest::OriginKind, prelude::Limited, VersionedLocation};
use sp_std::{marker::PhantomData, vec::Vec};

#[cfg(test)]
mod mock;
Expand All @@ -63,23 +42,16 @@ mod tests;

pub mod routers {
pub mod axelar_evm;
pub mod axelar_xcm;
pub mod ethereum_xcm;
}

pub use routers::{
axelar_evm::AxelarEVMRouter, axelar_xcm::AxelarXCMRouter, ethereum_xcm::EthereumXCMRouter,
};
pub use routers::axelar_evm::AxelarEVMRouter;

/// Maximum size allowed for a byte representation of an Axelar EVM chain
/// string, as found below:
/// <https://docs.axelar.dev/dev/reference/mainnet-chain-names>
/// <https://docs.axelar.dev/dev/reference/testnet-chain-names>
pub const MAX_AXELAR_EVM_CHAIN_SIZE: u32 = 16;

const FUNCTION_NAME: &str = "handle";
const MESSAGE_PARAM: &str = "message";

const AXELAR_FUNCTION_NAME: &str = "callContract";
const AXELAR_DESTINATION_CHAIN_PARAM: &str = "destinationChain";
const AXELAR_DESTINATION_CONTRACT_ADDRESS_PARAM: &str = "destinationContractAddress";
Expand All @@ -89,19 +61,17 @@ const AXELAR_PAYLOAD_PARAM: &str = "payload";
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
pub enum DomainRouter<T>
where
T: pallet_xcm_transactor::Config + pallet_ethereum_transaction::Config + pallet_evm::Config,
T: 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>),
AxelarXCM(AxelarXCMRouter<T>),
}

impl<T> Router for DomainRouter<T>
where
T: pallet_xcm_transactor::Config + pallet_ethereum_transaction::Config + pallet_evm::Config,
T: 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>>>,
Expand All @@ -110,17 +80,13 @@ where

fn init(&self) -> DispatchResult {
match self {
DomainRouter::EthereumXCM(r) => r.do_init(),
DomainRouter::AxelarEVM(r) => r.do_init(),
DomainRouter::AxelarXCM(r) => r.do_init(),
}
}

fn send(&self, sender: Self::Sender, message: Vec<u8>) -> DispatchResultWithPostInfo {
match self {
DomainRouter::EthereumXCM(r) => r.do_send(sender, message),
DomainRouter::AxelarEVM(r) => r.do_send(sender, message),
DomainRouter::AxelarXCM(r) => r.do_send(sender, message),
}
}
}
Expand Down Expand Up @@ -219,127 +185,3 @@ pub struct FeeValues {
/// The gas limit used when executing the EVM call.
pub gas_limit: U256,
}

/// A generic router used for executing XCM calls.
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
pub struct XCMRouter<T: pallet_xcm_transactor::Config> {
pub xcm_domain: XcmDomain<T::CurrencyId>,
}

impl<T: pallet_xcm_transactor::Config> XCMRouter<T> {
/// Sets the weight information for the provided XCM domain location, and
/// the fee per second for the provided fee asset location.
pub fn do_init(&self) -> DispatchResult {
Ok(())
}

/// Encodes the message to the required format and executes the
/// call via the XCM transactor pallet.
pub fn do_send(&self, sender: T::AccountId, msg: Vec<u8>) -> DispatchResultWithPostInfo {
let ethereum_xcm_call = get_encoded_ethereum_xcm_call::<T>(self.xcm_domain.clone(), msg)
.map_err(|_| DispatchError::Other("encoded ethereum xcm call retrieval"))?;

pallet_xcm_transactor::Pallet::<T>::transact_through_sovereign(
<T as frame_system::Config>::RuntimeOrigin::root(),
// The destination to which the message should be sent.
self.xcm_domain.location.clone(),
// The sender will pay for this transaction.
Some(sender),
// The currency in which we want to pay fees.
CurrencyPayment {
currency: Currency::AsCurrencyId(self.xcm_domain.fee_currency.clone()),
fee_amount: Some(self.xcm_domain.fee_amount),
},
// The call to be executed in the destination chain.
ethereum_xcm_call,
OriginKind::SovereignAccount,
TransactWeights {
transact_required_weight_at_most: self.xcm_domain.transact_required_weight_at_most,
overall_weight: Some(Limited(self.xcm_domain.overall_weight)),
},
// Opt-in on RefundSurplus
true,
)?;

Ok(PostDispatchInfo {
actual_weight: Some(self.xcm_domain.overall_weight),
pays_fee: Default::default(),
})
}
}

pub(crate) fn get_encoded_ethereum_xcm_call<T>(
xcm_domain: XcmDomain<T::CurrencyId>,
msg: Vec<u8>,
) -> Result<Vec<u8>, ()>
where
T: pallet_xcm_transactor::Config,
{
let input =
BoundedVec::<u8, ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }>>::try_from(msg)
.map_err(|_| ())?;

let mut encoded: Vec<u8> = Vec::new();

encoded.append(&mut xcm_domain.ethereum_xcm_transact_call_index.into_inner());

encoded.append(
&mut xcm_primitives::EthereumXcmTransaction::V1(xcm_primitives::EthereumXcmTransactionV1 {
gas_limit: U256::from(xcm_domain.max_gas_limit),
fee_payment: xcm_primitives::EthereumXcmFee::Auto,
action: pallet_ethereum::TransactionAction::Call(xcm_domain.contract_address),
value: U256::zero(),
input,
access_list: None,
})
.encode(),
);

Ok(encoded)
}

/// XcmDomain gathers all the required fields to build and send remote
/// calls to a specific XCM-based Domain.
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
pub struct XcmDomain<CurrencyId> {
/// The XCM multilocation of the domain.
pub location: Box<VersionedLocation>,

/// The ethereum_xcm::Call::transact call index on a given domain.
/// It should contain the pallet index + the `transact` call index, to which
/// we will append the eth_tx param.
///
/// You can obtain this value by building an ethereum_xcm::transact call
/// with Polkadot JS on the target chain.
pub ethereum_xcm_transact_call_index:
BoundedVec<u8, ConstU32<{ xcm_primitives::MAX_ETHEREUM_XCM_INPUT_SIZE }>>,

/// The target contract address on a given domain.
pub contract_address: H160,

/// The max gas limit for the execution of the EVM call
pub max_gas_limit: u64,

/// The max weight we want to pay for the execution of the Transact call in
/// the destination chain
pub transact_required_weight_at_most: Weight,

/// The overall max weight we want to pay for the whole XCM message (i.e,
/// all the instructions)
pub overall_weight: Weight,

/// The currency in which execution fees will be paid on
pub fee_currency: CurrencyId,

/// The fee we use to buy execution for the execution of the Transact call
pub fee_amount: u128,
}

#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, TypeInfo, MaxEncodedLen)]
/// XcmTransactInfo hold all the weight related information required for the XCM
/// transactor pallet.
pub struct XcmTransactInfo {
pub transact_extra_weight: Weight,
pub max_weight: Weight,
pub transact_extra_weight_signed: Option<Weight>,
}
Loading

0 comments on commit ce1133c

Please sign in to comment.