Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TRN-808 Sylo Data Pallet #917

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
26 changes: 26 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pallet-nft-peg = { path = "pallet/nft-peg", default-features = false }
pallet-sft = { path = "pallet/sft", default-features = false }
pallet-sft-rpc = { path = "pallet/sft/rpc", default-features = false }
pallet-sft-rpc-runtime-api = { path = "pallet/sft/rpc/runtime-api", default-features = false }
pallet-sylo = { path = "pallet/sylo", default-features = false }
pallet-token-approvals = { path = "pallet/token-approvals", default-features = false }
pallet-tx-fee-pot = { path = "pallet/tx-fee-pot", default-features = false }
pallet-vortex-distribution = { path = "pallet/vortex-distribution", default-features = false }
Expand Down
24 changes: 24 additions & 0 deletions pallet/common/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,3 +723,27 @@ macro_rules! impl_pallet_scheduler_config {
}
};
}

#[macro_export]
macro_rules! impl_pallet_sylo_config {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice; thanks for this

($test:ident) => {
parameter_types! {
pub const MaxResolvers: u32 = 10;
pub const MaxTags: u32 = 10;
pub const MaxEntries: u32 = 100;
pub const MaxServiceEndpoints: u32 = 10;
pub const StringLimit: u32 = 500;
}
impl pallet_sylo::Config for Test {
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type ApproveOrigin = EnsureRoot<AccountId>;
type MaxResolvers = MaxResolvers;
type MaxTags = MaxTags;
type MaxEntries = MaxEntries;
type MaxServiceEndpoints = MaxServiceEndpoints;
type StringLimit = StringLimit;
type WeightInfo = ();
}
};
}
1 change: 1 addition & 0 deletions pallet/fee-control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pallet-fee-proxy = { workspace = true, default-features = true }
pallet-dex = { workspace = true }
pallet-assets-ext = { workspace = true }
pallet-futurepass = { workspace = true }
pallet-sylo = { workspace = true }
seed-pallet-common= { workspace = true, default-features = true }

[features]
Expand Down
2 changes: 2 additions & 0 deletions pallet/fee-control/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ construct_runtime!(
Evm: pallet_evm,
Timestamp: pallet_timestamp,
Futurepass: pallet_futurepass,
Sylo: pallet_sylo,
MockPallet: mock_pallet::pallet,
FeeControl: pallet_fee_control,
}
Expand All @@ -54,6 +55,7 @@ impl_pallet_dex_config!(Test);
impl_pallet_timestamp_config!(Test);
impl_pallet_evm_config!(Test);
impl_pallet_futurepass_config!(Test);
impl_pallet_sylo_config!(Test);
impl_pallet_fee_control_config!(Test);

impl mock_pallet::pallet::Config for Test {}
Expand Down
2 changes: 2 additions & 0 deletions pallet/fee-proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pallet-evm = { workspace = true }
pallet-assets-ext = { workspace = true }
pallet-dex = { workspace = true }
pallet-futurepass = { workspace = true }
pallet-sylo = { workspace = true }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may need an entry in the std = [ feature below.

pallet-transaction-payment = { workspace = true }
precompile-utils = { workspace = true }

Expand All @@ -45,6 +46,7 @@ std = [
"pallet-assets-ext/std",
"pallet-futurepass/std",
"pallet-evm/std",
"pallet-sylo/std",
"pallet-transaction-payment/std",
"scale-info/std",
"seed-primitives/std",
Expand Down
126 changes: 102 additions & 24 deletions pallet/fee-proxy/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ where
+ pallet_dex::Config
+ pallet_evm::Config
+ pallet_assets_ext::Config
+ pallet_futurepass::Config,
+ pallet_futurepass::Config
+ pallet_sylo::Config,
<T as frame_system::Config>::RuntimeCall: IsSubType<crate::Call<T>>,
<T as frame_system::Config>::RuntimeCall: IsSubType<pallet_futurepass::Call<T>>,
<T as frame_system::Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
<T as Config>::RuntimeCall: IsSubType<pallet_evm::Call<T>>,
<T as Config>::RuntimeCall: IsSubType<pallet_futurepass::Call<T>>,
<T as Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
<T as pallet_futurepass::Config>::RuntimeCall: IsSubType<pallet_evm::Call<T>>,
<T as pallet_futurepass::Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
<T as Config>::OnChargeTransaction: OnChargeTransaction<T>,
<T as Config>::ErcIdConversion: ErcIdConversion<AssetId, EvmId = Address>,
Balance: From<<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::Balance>,
Expand All @@ -45,7 +49,10 @@ where
<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::LiquidityInfo;

/// Intercept the withdraw fee, and swap any tokens to gas tokens if the call is
/// pallet_fee_proxy.call_with_fee_preferences()
/// pallet_fee_proxy.call_with_fee_preferences().
///
/// This also additionally will force the Sylo token as the gas token if the call
/// is detected as a extrinsic for the sylo pallet.
fn withdraw_fee(
who: &T::AccountId,
call: &<T as frame_system::Config>::RuntimeCall,
Expand All @@ -65,12 +72,61 @@ where
}
}

let do_fee_swap = |who: &T::AccountId,
payment_asset: &AssetId,
mut total_fee: Balance,
max_payment: Balance|
-> Result<(), TransactionValidityError> {
let native_asset = <T as Config>::FeeAssetId::get();

// If the account has less balance than the minimum_deposit, we need to add
// the minimum deposit onto the total_fee.
// This is due to the preservation rules of the withdraw call made within
// <<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::withdraw_fee
let account_balance = pallet_assets_ext::Pallet::<T>::balance(native_asset, who);
// Minium balance is hardcoded to 1
let minimum_balance = pallet_assets_ext::Pallet::<T>::minimum_balance(native_asset);
if account_balance < minimum_balance {
total_fee = total_fee.saturating_add(minimum_balance);
}
let path: &[AssetId] = &[*payment_asset, native_asset];
pallet_dex::Pallet::<T>::do_swap_with_exact_target(
who,
total_fee,
max_payment,
path,
*who,
None,
)
.map_err(|_| InvalidTransaction::Stale)?;

Ok(())
};

let is_sylo_call = is_sylo_call::<T>(call);

// if the call is a sylo pallet call, then we always force a fee swap with the
// sylo token
if is_sylo_call {
// let payment_asset =
// pallet_sylo::Pallet::<T>::payment_asset().ok_or(InvalidTransaction::Payment)?;

let payment_asset =
pallet_sylo::SyloAssetId::<T>::get().ok_or(InvalidTransaction::Payment)?;

do_fee_swap(who, &payment_asset, Balance::from(fee), u128::MAX)?;
}

// Check whether this call has specified fee preferences
if let Some(call_with_fee_preferences { payment_asset, max_payment, call }) =
call.is_sub_type()
{
// prevent using the fee proxy if the inner call is a sylo call
if is_sylo_call {
Err(InvalidTransaction::Payment)?;
}

let mut total_fee: Balance = Balance::from(fee);
let native_asset = <T as Config>::FeeAssetId::get();

let mut add_evm_gas_cost =
|gas_limit: &u64,
Expand Down Expand Up @@ -127,27 +183,7 @@ where
add_evm_gas_cost(gas_limit, max_fee_per_gas, max_priority_fee_per_gas);
}

// If the account has less balance than the minimum_deposit, we need to add
// the minimum deposit onto the total_fee.
// This is due to the preservation rules of the withdraw call made within
// <<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::withdraw_fee
let account_balance = pallet_assets_ext::Pallet::<T>::balance(native_asset, who);
// Minium balance is hardcoded to 1
// pallet_assets_ext::Pallet::<T>::minimum_balance(native_asset);
let minimum_balance = pallet_assets_ext::Pallet::<T>::minimum_balance(native_asset);
if account_balance < minimum_balance {
total_fee = total_fee.saturating_add(minimum_balance);
}
let path: &[AssetId] = &[*payment_asset, native_asset];
pallet_dex::Pallet::<T>::do_swap_with_exact_target(
who,
total_fee,
*max_payment,
path,
*who,
None,
)
.map_err(|_| InvalidTransaction::Payment)?;
do_fee_swap(who, payment_asset, total_fee, *max_payment)?;
};

<<T as Config>::OnChargeTransaction as OnChargeTransaction<T>>::withdraw_fee(
Expand Down Expand Up @@ -182,3 +218,45 @@ where
)
}
}

/// Helper function to determine if a call is sylo pallet call that
/// should be paid using sylo tokens.
///
/// Will also determine if the inner call of a futurepass or
/// fee proxy call is a sylo call as well.
fn is_sylo_call<T>(call: &<T as frame_system::Config>::RuntimeCall) -> bool
where
T: Config
+ frame_system::Config<AccountId = AccountId>
+ pallet_futurepass::Config
+ pallet_sylo::Config,
<T as frame_system::Config>::RuntimeCall: IsSubType<crate::Call<T>>,
<T as frame_system::Config>::RuntimeCall: IsSubType<pallet_futurepass::Call<T>>,
<T as frame_system::Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
<T as Config>::RuntimeCall: IsSubType<pallet_futurepass::Call<T>>,
<T as Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
<T as pallet_futurepass::Config>::RuntimeCall: IsSubType<pallet_sylo::Call<T>>,
{
if match call.is_sub_type() {
Some(pallet_sylo::Call::register_resolver { .. }) => true,
Some(pallet_sylo::Call::update_resolver { .. }) => true,
Some(pallet_sylo::Call::unregister_resolver { .. }) => true,
Some(pallet_sylo::Call::create_validation_record { .. }) => true,
Some(pallet_sylo::Call::add_validation_record_entry { .. }) => true,
Some(pallet_sylo::Call::update_validation_record { .. }) => true,
Some(pallet_sylo::Call::delete_validation_record { .. }) => true,
_ => false,
} {
return true;
}

if let Some(pallet_futurepass::Call::proxy_extrinsic { call, .. }) = call.is_sub_type() {
return is_sylo_call::<T>(call.as_ref().into_ref());
}

if let Some(call_with_fee_preferences { call, .. }) = call.is_sub_type() {
return is_sylo_call::<T>(call.as_ref().into_ref());
}

false
}
5 changes: 3 additions & 2 deletions pallet/fee-proxy/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use pallet::*;
use frame_support::{
dispatch::{Dispatchable, GetDispatchInfo, PostDispatchInfo},
pallet_prelude::*,
traits::IsSubType,
traits::{IsSubType, IsType},
};
use frame_system::pallet_prelude::*;
use seed_pallet_common::{FeeConfig, MaintenanceCheckEVM};
Expand Down Expand Up @@ -63,7 +63,8 @@ pub mod pallet {
+ Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
+ GetDispatchInfo
+ From<frame_system::Call<Self>>
+ IsSubType<Call<Self>>;
+ IsSubType<Call<Self>>
+ IsType<<Self as frame_system::Config>::RuntimeCall>;
/// The system event type
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
/// The caller origin, overarching type of all pallets origins.
Expand Down
2 changes: 2 additions & 0 deletions pallet/fee-proxy/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ construct_runtime!(
Timestamp: pallet_timestamp,
Futurepass: pallet_futurepass,
FeeControl: pallet_fee_control,
Sylo: pallet_sylo,
}
);

Expand All @@ -53,6 +54,7 @@ impl_pallet_timestamp_config!(Test);
impl_pallet_evm_config!(Test);
impl_pallet_futurepass_config!(Test);
impl_pallet_fee_control_config!(Test);
impl_pallet_sylo_config!(Test);

// Mock ErcIdConversion for testing purposes
impl<RuntimeId> ErcIdConversion<RuntimeId> for Test
Expand Down
48 changes: 48 additions & 0 deletions pallet/sylo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[package]
name = "pallet-sylo"
version = "0.0.1"
description = "Root Network Sylo Pallet"
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

[dependencies]
hex = { workspace = true }
serde = { workspace = true }
scale-info = { workspace = true }
codec = { workspace = true }

frame-support = { workspace = true }
frame-system = { workspace = true }
frame-benchmarking = { workspace = true, optional = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-arithmetic = { workspace = true }
sp-std = { workspace = true }

seed-primitives = { workspace = true }
seed-pallet-common = { workspace = true }

[dev-dependencies]
sp-io = { workspace = true }
pallet-assets = { workspace = true }
pallet-balances = { workspace = true }
pallet-assets-ext = { workspace = true, default-features = true }

[features]
default = ["std"]
std = [
"codec/std",
"sp-runtime/std",
"frame-support/std",
"frame-system/std",
"sp-std/std",
"seed-primitives/std",
"seed-pallet-common/std",
"sp-io/std",
"frame-benchmarking?/std"
]
runtime-benchmarks = ["frame-benchmarking"]
try-runtime = ["frame-support/try-runtime"]
Loading