use crate::{accounts_config::AccountManagerCurrencyAdapter, Hash as HashPrimitive, *};
use frame_support::{
parameter_types,
traits::{
fungibles::{Balanced, Credit},
ConstU32, ConstU8, Contains, OffchainWorker, OnFinalize, OnIdle, OnInitialize,
OnRuntimeUpgrade,
},
weights::IdentityFee,
};
use pallet_asset_tx_payment::HandleCredit;
use polkadot_runtime_common::SlowAdjustingFeeUpdate;
use sp_runtime::traits::{BlakeTwo256, Zero};
parameter_types! {
pub const MinimumPeriod: u64 = SLOT_DURATION / 2;
}
impl frame_system::Config for Runtime {
type AccountData = pallet_balances::AccountData<Balance>;
type AccountId = AccountId;
type BaseCallFilter = frame_support::traits::Everything;
type Block = Block;
type BlockHashCount = BlockHashCount;
type BlockLength = circuit_runtime_types::RuntimeBlockLength;
type BlockWeights = circuit_runtime_types::RuntimeBlockWeights;
type DbWeight = RocksDbWeight;
type Hash = HashPrimitive;
type Hashing = BlakeTwo256;
type Lookup = AccountIdLookup<AccountId, ()>;
type MaxConsumers = frame_support::traits::ConstU32<16>;
type Nonce = u32;
type OnKilledAccount = ();
type OnNewAccount = ();
type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
type PalletInfo = PalletInfo;
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type RuntimeOrigin = RuntimeOrigin;
type SS58Prefix = SS58PrefixT1rn;
type SystemWeightInfo = ();
type Version = Version;
}
impl pallet_randomness_collective_flip::Config for Runtime {}
impl pallet_timestamp::Config for Runtime {
type MinimumPeriod = MinimumPeriod;
type Moment = u64;
type OnTimestampSet = Aura;
type WeightInfo = ();
}
parameter_types! {
pub const ExistentialDeposit: u128 = 1_u128;
}
impl pallet_balances::Config for Runtime {
type AccountStore = System;
type Balance = Balance;
type DustRemoval = ();
type ExistentialDeposit = ExistentialDeposit;
type FreezeIdentifier = ();
type MaxFreezes = ConstU32<0>;
type MaxHolds = ConstU32<0>;
type MaxLocks = ConstU32<50>;
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type RuntimeEvent = RuntimeEvent;
type RuntimeHoldReason = RuntimeHoldReason;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const TransactionByteFee: Balance = 1;
}
impl pallet_transaction_payment::Config for Runtime {
type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
type OnChargeTransaction = AccountManagerCurrencyAdapter<Balances, ()>;
type OperationalFeeMultiplier = ConstU8<5>;
type RuntimeEvent = RuntimeEvent;
type WeightToFee = IdentityFee<Balance>;
}
pub struct CreditToBlockAuthor;
impl HandleCredit<AccountId, Assets> for CreditToBlockAuthor {
fn handle_credit(credit: Credit<AccountId, Assets>) {
if let Some(author) = pallet_authorship::Pallet::<Runtime>::author() {
let author_credit = credit
.peek()
.saturating_mul(80_u32.into())
.saturating_div(<u32 as Into<Balance>>::into(100_u32));
let (author_cut, treasury_cut) = credit.split(author_credit);
match Assets::resolve(&author, author_cut) {
Ok(_) => (),
Err(_err) => {
log::error!("Failed to credit block author");
},
}
match Assets::resolve(&Treasury::account_id(), treasury_cut) {
Ok(_) => (),
Err(_err) => {
log::error!("Failed to credit treasury");
},
}
}
}
}
impl pallet_sudo::Config for Runtime {
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type WeightInfo = ();
}
impl pallet_utility::Config for Runtime {
type PalletsOrigin = OriginCaller;
type RuntimeCall = RuntimeCall;
type RuntimeEvent = RuntimeEvent;
type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
}
pub struct BaseCallFilter;
impl Contains<RuntimeCall> for BaseCallFilter {
fn contains(c: &RuntimeCall) -> bool {
match c {
RuntimeCall::System(_) => true,
RuntimeCall::ParachainSystem(_) => true,
RuntimeCall::Timestamp(_) => true,
RuntimeCall::Preimage(_) => true,
RuntimeCall::Scheduler(_) => true,
RuntimeCall::Utility(_) => true,
RuntimeCall::Identity(_) => true,
RuntimeCall::Balances(_) => true,
RuntimeCall::Assets(_) => true,
RuntimeCall::Treasury(_) => true,
RuntimeCall::AccountManager(method) => matches!(
method,
pallet_account_manager::Call::deposit { .. }
| pallet_account_manager::Call::finalize { .. }
),
RuntimeCall::CollatorSelection(_) => true,
RuntimeCall::Session(_) => true,
RuntimeCall::XcmpQueue(_) => true,
RuntimeCall::PolkadotXcm(_) => false,
RuntimeCall::DmpQueue(_) => true,
RuntimeCall::AssetRegistry(_) => true,
RuntimeCall::XDNS(_) => true,
RuntimeCall::ContractsRegistry(method) => matches!(
method,
pallet_contracts_registry::Call::add_new_contract { .. }
| pallet_contracts_registry::Call::purge { .. }
),
RuntimeCall::Circuit(method) => matches!(
method,
pallet_circuit::Call::on_local_trigger { .. }
| pallet_circuit::Call::on_xcm_trigger { .. }
| pallet_circuit::Call::on_remote_gateway_trigger { .. }
| pallet_circuit::Call::cancel_xtx { .. }
| pallet_circuit::Call::revert { .. }
| pallet_circuit::Call::on_extrinsic_trigger { .. }
| pallet_circuit::Call::bid_sfx { .. }
| pallet_circuit::Call::confirm_side_effect { .. }
),
RuntimeCall::Attesters(_) => true,
RuntimeCall::ThreeVm(_) => false,
RuntimeCall::Contracts(method) => matches!(
method,
pallet_3vm_contracts::Call::call { .. }
| pallet_3vm_contracts::Call::instantiate_with_code { .. }
| pallet_3vm_contracts::Call::instantiate { .. }
| pallet_3vm_contracts::Call::upload_code { .. }
| pallet_3vm_contracts::Call::remove_code { .. }
),
RuntimeCall::Evm(method) => matches!(
method,
pallet_3vm_evm::Call::withdraw { .. }
| pallet_3vm_evm::Call::call { .. }
| pallet_3vm_evm::Call::create { .. }
| pallet_3vm_evm::Call::create2 { .. } ),
RuntimeCall::Portal(_) => true,
_ => true,
}
}
}
pub struct MaintenanceFilter;
impl Contains<RuntimeCall> for MaintenanceFilter {
fn contains(c: &RuntimeCall) -> bool {
match c {
RuntimeCall::System(_) => true,
RuntimeCall::Scheduler(_) => true,
RuntimeCall::Utility(_) => true,
RuntimeCall::Balances(_) => true,
RuntimeCall::Assets(_) => true,
RuntimeCall::Sudo(_) => true,
RuntimeCall::ParachainSystem(_) => true,
RuntimeCall::Timestamp(_) => true,
RuntimeCall::Session(_) => true,
RuntimeCall::RococoBridge(_) => true,
RuntimeCall::KusamaBridge(_) => true,
RuntimeCall::PolkadotBridge(_) => true,
RuntimeCall::EthereumBridge(_) => true,
RuntimeCall::SepoliaBridge(_) => true,
#[allow(unreachable_patterns)] _ => false,
}
}
}
pub struct MaintenanceHooks;
impl OnInitialize<BlockNumber> for MaintenanceHooks {
fn on_initialize(n: BlockNumber) -> frame_support::weights::Weight {
AllPalletsWithSystem::on_initialize(n)
}
}
impl OnIdle<BlockNumber> for MaintenanceHooks {
fn on_idle(_n: BlockNumber, _max_weight: Weight) -> Weight {
Weight::zero()
}
}
impl OnRuntimeUpgrade for MaintenanceHooks {
fn on_runtime_upgrade() -> Weight {
AllPalletsWithSystem::on_runtime_upgrade()
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
AllPalletsWithSystem::pre_upgrade()
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(state: Vec<u8>) -> Result<(), &'static str> {
AllPalletsWithSystem::post_upgrade()
}
}
impl OnFinalize<BlockNumber> for MaintenanceHooks {
fn on_finalize(n: BlockNumber) {
AllPalletsWithSystem::on_finalize(n)
}
}
impl OffchainWorker<BlockNumber> for MaintenanceHooks {
fn offchain_worker(n: BlockNumber) {
AllPalletsWithSystem::offchain_worker(n)
}
}
impl pallet_maintenance_mode::Config for Runtime {
type MaintenanceCallFilter = MaintenanceFilter;
type MaintenanceExecutiveHooks = AllPalletsWithSystem;
type MaintenanceOrigin = EnsureRoot<AccountId>;
type NormalCallFilter = BaseCallFilter;
type NormalExecutiveHooks = AllPalletsWithSystem;
type RuntimeEvent = RuntimeEvent;
}
#[cfg(test)]
mod tests {
use super::*;
use codec::Compact;
use pallet_circuit::Outcome;
use sp_runtime::{AccountId32, MultiAddress};
use t3rn_primitives::claimable::BenefitSource;
#[test]
fn base_filter_works_with_allowed_and_disallowed_calls() {
let call = frame_system::Call::remark { remark: vec![] }.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_timestamp::Call::set { now: 0 }.into();
assert!(BaseCallFilter::contains(&call));
let prev_call = pallet_identity::Call::add_registrar {
account: MultiAddress::Address32([0; 32]),
}
.into();
assert!(BaseCallFilter::contains(&prev_call));
let call = pallet_account_manager::Call::finalize {
charge_id: Default::default(),
outcome: Outcome::Commit,
maybe_recipient: Default::default(),
maybe_actual_fees: Default::default(),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_xdns::Call::purge_gateway_record {
requester: AccountId32::new([0; 32]),
gateway_id: Default::default(),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_contracts_registry::Call::purge {
requester: AccountId32::new([0; 32]),
contract_id: Default::default(),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_circuit::Call::bid_sfx {
sfx_id: Default::default(),
bid_amount: 0,
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_balances::Call::transfer {
dest: MultiAddress::Address32([0; 32]),
value: 0,
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_assets::Call::create {
id: Default::default(),
admin: MultiAddress::Address32([0; 32]),
min_balance: 0,
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_treasury::Call::<Runtime, ()>::propose_spend {
value: 0,
beneficiary: MultiAddress::Address32([0; 32]),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_3vm_evm::Call::withdraw {
address: Default::default(),
value: 0,
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_3vm_contracts::Call::call {
dest: MultiAddress::Address32([0; 32]),
data: vec![],
gas_limit: 0.into(),
value: 0,
storage_deposit_limit: Some(Compact(0)),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_sudo::Call::sudo {
call: Box::new(frame_system::Call::remark { remark: vec![] }.into()),
}
.into();
assert!(BaseCallFilter::contains(&call));
let call = pallet_portal::Call::register_gateway {
gateway_id: Default::default(),
token_id: Default::default(),
verification_vendor: Default::default(),
execution_vendor: Default::default(),
codec: Default::default(),
registrant: Default::default(),
escrow_account: Default::default(),
allowed_side_effects: Default::default(),
token_props: Default::default(),
encoded_registration_data: Default::default(),
}
.into();
assert!(BaseCallFilter::contains(&call));
}
#[test]
fn maintenance_filter_works_with_allowed_and_disallowed_calls() {
let call = frame_system::Call::remark { remark: vec![] }.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_utility::Call::as_derivative {
index: 0,
call: Box::new(call),
}
.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_balances::Call::transfer {
dest: MultiAddress::Address32([0; 32]),
value: 0,
}
.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_assets::Call::create {
id: Default::default(),
admin: MultiAddress::Address32([0; 32]),
min_balance: 0,
}
.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_timestamp::Call::set { now: 0 }.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_sudo::Call::sudo {
call: Box::new(frame_system::Call::remark { remark: vec![] }.into()),
}
.into();
assert!(MaintenanceFilter::contains(&call));
let call = pallet_3vm_evm::Call::withdraw {
address: Default::default(),
value: 0,
}
.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_identity::Call::add_registrar {
account: MultiAddress::Address32([0; 32]),
}
.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_treasury::Call::<Runtime, ()>::reject_proposal { proposal_id: 0 }.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_account_manager::Call::deposit {
charge_id: Default::default(),
payee: AccountId32::new([0; 32]),
charge_fee: 0,
offered_reward: 0,
source: BenefitSource::BootstrapPool,
role: pallet_circuit::CircuitRole::Relayer,
recipient: Default::default(),
maybe_asset_id: Default::default(),
}
.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_xdns::Call::purge_gateway_record {
requester: AccountId32::new([0; 32]),
gateway_id: Default::default(),
}
.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_contracts_registry::Call::purge {
requester: AccountId32::new([0; 32]),
contract_id: Default::default(),
}
.into();
assert!(!MaintenanceFilter::contains(&call));
let call = pallet_circuit::Call::bid_sfx {
sfx_id: Default::default(),
bid_amount: 0,
}
.into();
assert!(!MaintenanceFilter::contains(&call));
}
}