Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bridges/snowbridge/pallets/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ pub mod pallet {
use super::*;

#[pallet::pallet]
#[pallet::storage_version(migration::STORAGE_VERSION)]
pub struct Pallet<T>(_);

#[pallet::config]
Expand Down
135 changes: 129 additions & 6 deletions bridges/snowbridge/pallets/system/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,30 @@
// SPDX-FileCopyrightText: 2023 Snowfork <hello@snowfork.com>
//! Governance API for controlling the Ethereum side of the bridge
use super::*;
use frame_support::traits::OnRuntimeUpgrade;
use frame_support::{
migrations::VersionedMigration,
pallet_prelude::*,
traits::{OnRuntimeUpgrade, UncheckedOnRuntimeUpgrade},
weights::Weight,
};
use log;
use sp_std::marker::PhantomData;

#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;

pub mod v0 {
use frame_support::{pallet_prelude::*, weights::Weight};
const LOG_TARGET: &str = "ethereum_system::migration";

use super::*;
/// The in-code storage version.
pub const STORAGE_VERSION: StorageVersion = StorageVersion::new(1);

const LOG_TARGET: &str = "ethereum_system::migration";
pub mod v0 {
use super::*;

pub struct InitializeOnUpgrade<T, BridgeHubParaId, AssetHubParaId>(
sp_std::marker::PhantomData<(T, BridgeHubParaId, AssetHubParaId)>,
PhantomData<(T, BridgeHubParaId, AssetHubParaId)>,
);

impl<T, BridgeHubParaId, AssetHubParaId> OnRuntimeUpgrade
for InitializeOnUpgrade<T, BridgeHubParaId, AssetHubParaId>
where
Expand Down Expand Up @@ -72,3 +80,118 @@ pub mod v0 {
}
}
}

pub mod v1 {
use super::*;

#[cfg(feature = "try-runtime")]
use sp_core::U256;

/// Descreases the fee per gas.
pub struct FeePerGasMigration<T>(PhantomData<T>);

#[cfg(feature = "try-runtime")]
impl<T> FeePerGasMigration<T>
where
T: Config,
{
/// Calculate the fee required to pay for gas on Ethereum.
fn calculate_remote_fee(params: &PricingParametersOf<T>) -> U256 {
use snowbridge_core::outbound::{
AgentExecuteCommand, Command, ConstantGasMeter, GasMeter,
};
let command = Command::AgentExecute {
agent_id: H256::zero(),
command: AgentExecuteCommand::TransferToken {
token: H160::zero(),
recipient: H160::zero(),
amount: 0,
},
};
let gas_used_at_most = ConstantGasMeter::maximum_gas_used_at_most(&command);
params
.fee_per_gas
.saturating_mul(gas_used_at_most.into())
.saturating_add(params.rewards.remote)
}
}

/// The percentage gas increase. We must adjust the fee per gas by this percentage.
const GAS_INCREASE_PERCENTAGE: u64 = 70;

impl<T> UncheckedOnRuntimeUpgrade for FeePerGasMigration<T>
where
T: Config,
{
fn on_runtime_upgrade() -> Weight {
let mut params = Pallet::<T>::parameters();

let old_fee_per_gas = params.fee_per_gas;

// Fee per gas can be set based on a percentage in order to keep the remote fee the
// same.
params.fee_per_gas = params.fee_per_gas * GAS_INCREASE_PERCENTAGE / 100;

log::info!(
target: LOG_TARGET,
"Fee per gas migrated from {old_fee_per_gas:?} to {0:?}.",
params.fee_per_gas,
);

PricingParameters::<T>::put(params);
T::DbWeight::get().reads_writes(1, 1)
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
use codec::Encode;

let params = Pallet::<T>::parameters();
let remote_fee = Self::calculate_remote_fee(&params);

log::info!(
target: LOG_TARGET,
"Pre fee per gas migration: pricing parameters = {params:?}, remote_fee = {remote_fee:?}"
);
Ok((params, remote_fee).encode())
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), TryRuntimeError> {
use codec::Decode;

let (old_params, old_remote_fee): (PricingParametersOf<T>, U256) =
Decode::decode(&mut &state[..]).unwrap();

let params = Pallet::<T>::parameters();
ensure!(old_params.exchange_rate == params.exchange_rate, "Exchange rate unchanged.");
ensure!(old_params.rewards == params.rewards, "Rewards unchanged.");
ensure!(
(old_params.fee_per_gas * GAS_INCREASE_PERCENTAGE / 100) == params.fee_per_gas,
"Fee per gas decreased."
);
ensure!(old_params.multiplier == params.multiplier, "Multiplier unchanged.");

let remote_fee = Self::calculate_remote_fee(&params);
ensure!(
remote_fee <= old_remote_fee,
"The remote fee can cover the cost of the previous fee."
);

log::info!(
target: LOG_TARGET,
"Post fee per gas migration: pricing parameters = {params:?} remote_fee = {remote_fee:?}"
);
Ok(())
}
}
}

/// Run the migration of the gas price and increment the pallet version so it cannot be re-run.
pub type FeePerGasMigrationV0ToV1<T> = VersionedMigration<
0,
1,
v1::FeePerGasMigration<T>,
Pallet<T>,
<T as frame_system::Config>::DbWeight,
>;
4 changes: 2 additions & 2 deletions bridges/snowbridge/primitives/core/src/outbound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ impl GasMeter for ConstantGasMeter {
// * No gas refund for clearing storage slot of source account in ERC20 contract
// * Assume dest account in ERC20 contract does not yet have a storage slot
// * ERC20.transferFrom possibly does other business logic besides updating balances
AgentExecuteCommand::TransferToken { .. } => 100_000,
AgentExecuteCommand::TransferToken { .. } => 200_000,
},
Command::Upgrade { initializer, .. } => {
let initializer_max_gas = match *initializer {
Expand All @@ -457,7 +457,7 @@ impl GasMeter for ConstantGasMeter {
},
Command::SetTokenTransferFees { .. } => 60_000,
Command::SetPricingParameters { .. } => 60_000,
Command::TransferNativeToken { .. } => 100_000,
Command::TransferNativeToken { .. } => 200_000,
Command::RegisterForeignToken { .. } => 1_200_000,
Command::MintForeignToken { .. } => 100_000,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ pub mod bridging {
/// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/ROC 1/400 and fee_per_gas 20 GWEI = 2200698000000 + *25%)
/// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs
/// Polkadot uses 10 decimals, Kusama and Rococo 12 decimals.
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,7 @@ pub mod bridging {
/// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/WND 1/400 and fee_per_gas 20 GWEI = 2200698000000 + *25%)
/// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs
/// Polkadot uses 10 decimals, Kusama,Rococo,Westend 12 decimals.
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ pub type Migrations = (
ConstU32<BRIDGE_HUB_ID>,
ConstU32<ASSET_HUB_ID>,
>,
snowbridge_pallet_system::migration::FeePerGasMigrationV0ToV1<Runtime>,
pallet_bridge_messages::migration::v1::MigrationToV1<
Runtime,
bridge_to_westend_config::WithBridgeHubWestendMessagesInstance,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use sp_runtime::{
};

parameter_types! {
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
}

fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys<Runtime> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ pub type Migrations = (
ConstU32<BRIDGE_HUB_ID>,
ConstU32<ASSET_HUB_ID>,
>,
snowbridge_pallet_system::migration::FeePerGasMigrationV0ToV1<Runtime>,
bridge_to_ethereum_config::migrations::MigrationForXcmV5<Runtime>,
// permanent
pallet_xcm::migration::MigrateToLatestXcmVersion<Runtime>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use sp_runtime::{
};

parameter_types! {
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_833_568_200_000;
}

fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys<Runtime> {
Expand Down
22 changes: 22 additions & 0 deletions prdoc/pr_8258.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
title: '[stable2412] Backport Snowbridge - Update TransferToken command gas limit.'

doc:
- audience: Runtime Dev
description: |
Transfering certain ERC20 tokens require more gas than 100_000 gas. An example is LDO token which requires 140_000 gas.
This change updates the gas limit to 200_000 and also updates the default fees for testnet runtimes.
NOTE: make sure to update the relevant runtime fees to account for this change.

crates:
- name: asset-hub-westend-runtime
bump: patch
- name: asset-hub-rococo-runtime
bump: patch
- name: bridge-hub-westend-runtime
bump: patch
- name: bridge-hub-rococo-runtime
bump: patch
- name: snowbridge-core
bump: patch
- name: snowbridge-pallet-system
bump: patch
Loading