Skip to content

Commit

Permalink
use weth for execution fees on AH
Browse files Browse the repository at this point in the history
  • Loading branch information
claravanstaden committed Dec 2, 2024
1 parent d77a1ee commit f40cfd4
Show file tree
Hide file tree
Showing 7 changed files with 34 additions and 157 deletions.
6 changes: 2 additions & 4 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use crate::{weights::WeightInfo, Config, Error, Junction::AccountId32, Location};
use frame_support::weights::WeightToFee;
use snowbridge_router_primitives::inbound::v2::{ConvertMessage, Message};
use sp_core::{Get, H256};
use sp_runtime::{DispatchError, Saturating};
use sp_core::H256;
use sp_runtime::{DispatchError};
use xcm::latest::Xcm;

pub fn dry_run<T>(message: Message) -> Result<(Xcm<()>, T::Balance), DispatchError>
Expand All @@ -21,9 +21,7 @@ where
// Calculate fee. Consists of the cost of the "submit" extrinsic as well as the XCM execution
// prologue fee (static XCM part of the message that is execution on AH).
let weight_fee = T::WeightToFee::weight_to_fee(&T::WeightInfo::submit());
let xcm_prologue_fee = T::XcmPrologueFee::get();
let fee: u128 = weight_fee
.saturating_add(xcm_prologue_fee)
.try_into()
.map_err(|_| Error::<T>::InvalidFee)?;

Expand Down
12 changes: 0 additions & 12 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ use frame_support::{
use frame_system::{ensure_signed, pallet_prelude::*};
use scale_info::TypeInfo;
use snowbridge_core::{
fees::burn_fees,
inbound::{Message, VerificationError, Verifier},
sparse_bitmap::SparseBitmap,
BasicOperatingMode,
Expand All @@ -65,7 +64,6 @@ use sp_std::vec;
use types::Nonce;
pub use weights::WeightInfo;
use xcm::prelude::{send_xcm, Junction::*, Location, SendError as XcmpSendError, SendXcm, *};
use xcm_executor::traits::TransactAsset;

#[cfg(feature = "runtime-benchmarks")]
use snowbridge_beacon_primitives::BeaconHeader;
Expand Down Expand Up @@ -108,14 +106,10 @@ pub mod pallet {
type AssetHubParaId: Get<u32>;
/// Convert a command from Ethereum to an XCM message.
type MessageConverter: ConvertMessage;
/// The AH XCM execution fee for the static part of the XCM message.
type XcmPrologueFee: Get<BalanceOf<Self>>;
/// Used to burn fees from the origin account (the relayer), which will be teleported to AH.
type Token: Mutate<Self::AccountId> + Inspect<Self::AccountId>;
/// Used for the dry run API implementation.
type Balance: Balance + From<u128>;
/// Used to burn fees.
type AssetTransactor: TransactAsset;
#[cfg(feature = "runtime-benchmarks")]
type Helper: BenchmarkHelper<Self>;
}
Expand Down Expand Up @@ -234,12 +228,6 @@ pub mod pallet {

let xcm = Self::do_convert(message, origin_account_location.clone())?;

// Burn the required fees for the static XCM message part
burn_fees::<T::AssetTransactor, BalanceOf<T>>(
origin_account_location,
T::XcmPrologueFee::get(),
)?;

// Todo: Deposit fee(in Ether) to RewardLeger which should cover all of:
// T::RewardLeger::deposit(who, envelope.fee.into())?;
// a. The submit extrinsic cost on BH
Expand Down
10 changes: 4 additions & 6 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use super::*;
use crate::{self as inbound_queue_v2};
use frame_support::{
derive_impl, parameter_types,
traits::{ConstU128, ConstU32},
traits::ConstU32,
weights::IdentityFee,
};
use hex_literal::hex;
Expand Down Expand Up @@ -104,6 +104,7 @@ impl Verifier for MockVerifier {
}

const GATEWAY_ADDRESS: [u8; 20] = hex!["eda338e4dc46038493b885327842fd3e301cab39"];
const WETH_ADDRESS: [u8; 20] = hex!["fff9976782d46cc05630d1f6ebab18b2324d6b14"];

#[cfg(feature = "runtime-benchmarks")]
impl<T: snowbridge_pallet_ethereum_client::Config> BenchmarkHelper<T> for Test {
Expand Down Expand Up @@ -149,12 +150,11 @@ impl MaybeEquivalence<TokenId, Location> for MockTokenIdConvert {
parameter_types! {
pub const EthereumNetwork: xcm::v5::NetworkId = xcm::v5::NetworkId::Ethereum { chain_id: 11155111 };
pub const GatewayAddress: H160 = H160(GATEWAY_ADDRESS);
pub const WethAddress: H160 = H160(WETH_ADDRESS);
pub const InboundQueuePalletInstance: u8 = 80;
pub AssetHubLocation: InteriorLocation = Parachain(1000).into();
}

const XCM_PROLOGUE_FEE: u128 = 1_000_000_000_000;

impl inbound_queue_v2::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Verifier = MockVerifier;
Expand All @@ -167,12 +167,10 @@ impl inbound_queue_v2::Config for Test {
EthereumNetwork,
InboundQueuePalletInstance,
MockTokenIdConvert,
ConstU128<XCM_PROLOGUE_FEE>,
WethAddress,
>;
type Token = Balances;
type Balance = u128;
type XcmPrologueFee = ConstU128<XCM_PROLOGUE_FEE>;
type AssetTransactor = SuccessfulTransactor;
#[cfg(feature = "runtime-benchmarks")]
type Helper = Test;
}
Expand Down
31 changes: 6 additions & 25 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,6 @@ fn test_submit_happy_path() {
});
}

#[test]
fn test_submit_xcm_invalid_channel() {
new_tester().execute_with(|| {
let relayer: AccountId = Keyring::Bob.into();
let origin = RuntimeOrigin::signed(relayer);

// Submit message
let message = Message {
event_log: mock_event_log_invalid_channel(),
proof: Proof {
receipt_proof: Default::default(),
execution_proof: mock_execution_proof(),
},
};
assert_noop!(
InboundQueue::submit(origin.clone(), message.clone()),
Error::<Test>::InvalidChannel,
);
});
}

#[test]
fn test_submit_with_invalid_gateway() {
new_tester().execute_with(|| {
Expand Down Expand Up @@ -151,7 +130,7 @@ fn test_set_operating_mode_root_only() {
fn test_send_native_erc20_token_payload() {
new_tester().execute_with(|| {
// To generate test data: forge test --match-test testSendEther -vvvv
let payload = hex!("29e3b139f4393adda86303fcdaa35f60bb7092bf04005615deb798bb3e4dfa0139dfa1b3d433cc23b72f0000b2d3595bf00600000000000000000000").to_vec();
let payload = hex!("29e3b139f4393adda86303fcdaa35f60bb7092bf0030ef7dba020000000000000000000004005615deb798bb3e4dfa0139dfa1b3d433cc23b72f0000b2d3595bf00600000000000000000000").to_vec();
let message = MessageV2::decode(&mut payload.as_ref());
assert_ok!(message.clone());

Expand Down Expand Up @@ -179,19 +158,21 @@ fn test_send_native_erc20_token_payload() {
#[test]
fn test_send_foreign_erc20_token_payload() {
new_tester().execute_with(|| {
let payload = hex!("29e3b139f4393adda86303fcdaa35f60bb7092bf040197874824853fb4ad04794ccfd1cc8d2a7463839cfcbc6a315a1045c60ab85f400000b2d3595bf00600000000000000000000").to_vec();
let payload = hex!("29e3b139f4393adda86303fcdaa35f60bb7092bf0030ef7dba0200000000000000000000040197874824853fb4ad04794ccfd1cc8d2a7463839cfcbc6a315a1045c60ab85f400000b2d3595bf00600000000000000000000").to_vec();
let message = MessageV2::decode(&mut payload.as_ref());
assert_ok!(message.clone());

let inbound_message = message.unwrap();
let inbound_message = message.unwrap();

let expected_fee = 3_000_000_000_000u128;
let expected_origin: H160 = hex!("29e3b139f4393adda86303fcdaa35f60bb7092bf").into();
let expected_token_id: H256 = hex!("97874824853fb4ad04794ccfd1cc8d2a7463839cfcbc6a315a1045c60ab85f40").into();
let expected_value = 500000000000000000u128;
let expected_xcm: Vec<u8> = vec![];
let expected_claimer: Option<Vec<u8>> = None;

assert_eq!(expected_origin, inbound_message.origin);
assert_eq!(expected_fee, inbound_message.fee);
assert_eq!(1, inbound_message.assets.len());
if let Asset::ForeignTokenERC20 { token_id, value } = &inbound_message.assets[0] {
assert_eq!(expected_token_id, *token_id);
Expand All @@ -207,7 +188,7 @@ fn test_send_foreign_erc20_token_payload() {
#[test]
fn test_register_token_inbound_message_with_xcm_and_claimer() {
new_tester().execute_with(|| {
let payload = hex!("5991a2df15a8f6a256d3ec51e99254cd3fb576a904005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000300508020401000002286bee0a015029e3b139f4393adda86303fcdaa35f60bb7092bf").to_vec();
let payload = hex!("5991a2df15a8f6a256d3ec51e99254cd3fb576a90030ef7dba020000000000000000000004005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000300508020401000002286bee0a015029e3b139f4393adda86303fcdaa35f60bb7092bf").to_vec();
let message = MessageV2::decode(&mut payload.as_ref());
assert_ok!(message.clone());

Expand Down
27 changes: 15 additions & 12 deletions bridges/snowbridge/primitives/router/src/inbound/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use sp_core::{Get, RuntimeDebug, H160, H256};
use sp_runtime::traits::MaybeEquivalence;
use sp_std::prelude::*;
use xcm::{
prelude::{Junction::AccountKey20, *},
prelude::{Asset as XcmAsset, Junction::AccountKey20, *},
MAX_XCM_DECODE_DEPTH,
};

Expand All @@ -23,6 +23,8 @@ const LOG_TARGET: &str = "snowbridge-router-primitives";
pub struct Message {
/// The origin address
pub origin: H160,
/// Fee in weth to cover the xcm execution on AH.
pub fee: u128,
/// The assets
pub assets: Vec<Asset>,
/// The command originating from the Gateway contract
Expand Down Expand Up @@ -67,24 +69,24 @@ pub trait ConvertMessage {
fn convert(message: Message, origin_account: Location) -> Result<Xcm<()>, ConvertMessageError>;
}

pub struct MessageToXcm<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, XcmPrologueFee>
pub struct MessageToXcm<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, WethAddress>
where
EthereumNetwork: Get<NetworkId>,
InboundQueuePalletInstance: Get<u8>,
ConvertAssetId: MaybeEquivalence<TokenId, Location>,
XcmPrologueFee: Get<u128>,
WethAddress: Get<H160>,
{
_phantom:
PhantomData<(EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, XcmPrologueFee)>,
PhantomData<(EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, WethAddress)>,
}

impl<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, XcmPrologueFee> ConvertMessage
for MessageToXcm<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, XcmPrologueFee>
impl<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, WethAddress> ConvertMessage
for MessageToXcm<EthereumNetwork, InboundQueuePalletInstance, ConvertAssetId, WethAddress>
where
EthereumNetwork: Get<NetworkId>,
InboundQueuePalletInstance: Get<u8>,
ConvertAssetId: MaybeEquivalence<TokenId, Location>,
XcmPrologueFee: Get<u128>,
WethAddress: Get<H160>,
{
fn convert(
message: Message,
Expand Down Expand Up @@ -112,13 +114,14 @@ where

let network = EthereumNetwork::get();

let fee_asset = Location::new(1, Here);
let fee: xcm::prelude::Asset = (fee_asset.clone(), XcmPrologueFee::get()).into();
// use weth as asset
let fee_asset = Location::new(2, [GlobalConsensus(EthereumNetwork::get()), AccountKey20 { network: None, key: WethAddress::get().into() } ]);
let fee: XcmAsset = (fee_asset.clone(), message.fee).into();
let mut instructions = vec![
ReceiveTeleportedAsset(fee.clone().into()),
PayFees { asset: fee },
DescendOrigin(PalletInstance(InboundQueuePalletInstance::get()).into()),
UniversalOrigin(GlobalConsensus(network)),
ReserveAssetDeposited(fee.clone().into()),
PayFees { asset: fee },
];

for asset in &message.assets {
Expand Down Expand Up @@ -150,6 +153,7 @@ where

// Set the alias origin to the original sender on Ethereum. Important to be before the
// arbitrary XCM that is appended to the message on the next line.
// TODO allow address from Ethereum to create foreign assets on AH
// instructions.push(AliasOrigin(origin_location.into()));

// Add the XCM sent in the message to the end of the xcm instruction
Expand All @@ -158,7 +162,6 @@ where
let appendix = vec![
RefundSurplus,
// Refund excess fees to the relayer
// TODO maybe refund all fees to the relayer instead of just DOT?
DepositAsset {
assets: Wild(AllOf { id: AssetId(fee_asset.into()), fun: WildFungible }),
beneficiary: origin_account_location,
Expand Down
Loading

0 comments on commit f40cfd4

Please sign in to comment.