#![cfg_attr(not(feature = "std"), no_std)]
#![recursion_limit = "256"]
#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
#[cfg(feature = "std")]
include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
use codec::Encode;
use sp_api::impl_runtime_apis;
use sp_consensus_aura::sr25519::AuthorityId as AuraId;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata, U256};
#[cfg(feature = "try-runtime")]
use sp_runtime::TryRuntimeError;
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys, traits,
traits::{BlakeTwo256, Block as BlockT, OpaqueKeys},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, FixedPointNumber, Permill, SaturatedConversion,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
pub use core_primitives::{
AccountId, ApiError as PhronApiError, AuthorityId as PhronId, Balance, Block as PhronBlock,
BlockNumber, Hash, Index, Nonce, SessionAuthorityData, SessionCommittee, SessionValidatorError,
Signature, TransactionPriority, Version as FinalityVersion, VersionChange,
DEFAULT_BAN_REASON_LENGTH, DEFAULT_MAX_WINNERS, DEFAULT_SESSIONS_PER_ERA,
DEFAULT_SESSION_PERIOD, MAX_BLOCK_SIZE, MILLISECS_PER_BLOCK,
};
pub use frame_support::{
construct_runtime,
pallet_prelude::{Get, PhantomData},
parameter_types,
traits::{
ConstBool, ConstU128, ConstU32, ConstU64, ConstU8, Contains, Currency,
EstimateNextSessionRotation, FindAuthor, KeyOwnerProofSystem, OnUnbalanced, Randomness,
StorageInfo,
},
weights::{
constants::{
BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
},
IdentityFee, Weight,
},
StorageValue,
};
pub use frame_system::Call as SystemCall;
pub use pallet_balances::Call as BalancesCall;
use pallet_evm::OnChargeEVMTransaction as OnChargeEVMTransactionT;
use pallet_session::historical as pallet_session_historical;
pub use pallet_timestamp::Call as TimestampCall;
use pallet_transaction_payment::{CurrencyAdapter, Multiplier};
#[cfg(any(feature = "std", test))]
pub use sp_runtime::BuildStorage;
pub use sp_staking::StakerStatus;
mod precompiles;
use precompiles::FrontierPrecompiles;
mod currency;
mod ethereum_transaction;
mod impl_on_charge_evm_transaction;
mod voter_bags;
use ethereum_transaction::TransactionData;
pub use currency::phronesis;
pub mod opaque {
use super::*;
pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type Block = PhronBlock;
pub type BlockId = generic::BlockId<Block>;
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub phron: Phron,
}
}
}
#[sp_version::runtime_version]
pub const VERSION: RuntimeVersion = RuntimeVersion {
spec_name: create_runtime_str!("phronesis"),
impl_name: create_runtime_str!("phronesis"),
authoring_version: 1,
spec_version: 100,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
state_version: 1,
};
pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES;
pub const EPOCH_DURATION_IN_SLOTS: u64 = {
const SLOT_FILL_RATE: f64 = MILLISECS_PER_BLOCK as f64 / SLOT_DURATION as f64;
(EPOCH_DURATION_IN_BLOCKS as f64 * SLOT_FILL_RATE) as u64
};
pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;
pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);
pub const HOURS: BlockNumber = MINUTES * 60;
pub const DAYS: BlockNumber = HOURS * 24;
#[cfg(feature = "std")]
pub fn native_version() -> NativeVersion {
NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
}
const NORMAL_DISPATCH_RATIO: sp_runtime::Perbill = sp_runtime::Perbill::from_percent(75);
const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts(
frame_support::weights::constants::WEIGHT_REF_TIME_PER_MILLIS.saturating_mul(400),
0,
);
parameter_types! {
pub const BlockHashCount: BlockNumber = 256;
pub const Version: RuntimeVersion = VERSION;
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::with_sensible_defaults(
MAXIMUM_BLOCK_WEIGHT.set_proof_size(u64::MAX), NORMAL_DISPATCH_RATIO,
);
pub BlockLength: frame_system::limits::BlockLength = frame_system::limits::BlockLength
::max_with_normal_ratio(MAX_BLOCK_SIZE, NORMAL_DISPATCH_RATIO);
pub const SS58Prefix: u8 = 23;
}
impl frame_system::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = BlockWeights;
type BlockLength = BlockLength;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = Nonce;
type Hash = Hash;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = traits::IdentityLookup<AccountId>;
type Block = Block;
type BlockHashCount = BlockHashCount;
type DbWeight = RocksDbWeight;
type Version = Version;
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<Balance>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = frame_system::weights::SubstrateWeight<Runtime>;
type SS58Prefix = SS58Prefix;
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
impl pallet_aura::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type AuthorityId = AuraId;
type MaxAuthorities = ConstU32<100_000>;
type SessionPeriod = SessionPeriod;
type MaxSplits = ConstU32<3>;
type DisabledValidators = ();
type AllowMultipleBlocksPerSlot = ConstBool<false>;
}
impl pallet_authorship::Config for Runtime {
type FindAuthor = pallet_session::FindAccountFromAuthorIndex<Self, Aura>;
type EventHandler = (CommitteeManagement,);
}
impl_opaque_keys! {
pub struct SessionKeys {
pub aura: Aura,
pub phron: Phron,
}
}
pub struct SessionInfoImpl;
#[cfg_attr(coverage_nightly, coverage(off))]
impl core_primitives::SessionInfoProvider<BlockNumber> for SessionInfoImpl {
fn current_session() -> core_primitives::SessionIndex {
pallet_session::CurrentIndex::<Runtime>::get()
}
fn next_session_block_number(current_block: BlockNumber) -> Option<BlockNumber> {
<Runtime as pallet_session::Config>::NextSessionRotation::estimate_next_session_rotation(
current_block,
)
.0
}
}
impl pallet_phron::Config for Runtime {
type AuthorityId = PhronId;
type RuntimeEvent = RuntimeEvent;
type SessionInfoProvider = SessionInfoImpl;
type SessionManager = pallet_committee_management::SessionAndEraManager<
Staking,
Elections,
pallet_session::historical::NoteHistoricalRoot<Runtime, Staking>,
Runtime,
>;
type NextSessionAuthorityProvider = Session;
}
parameter_types! {
pub const MaximumBanReasonLength: u32 = DEFAULT_BAN_REASON_LENGTH;
pub const MaxWinners: u32 = DEFAULT_MAX_WINNERS;
}
impl pallet_elections::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type DataProvider = Staking;
type ValidatorProvider = Staking;
type MaxWinners = MaxWinners;
type BannedValidators = CommitteeManagement;
}
impl pallet_committee_management::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type BanHandler = Elections;
type EraInfoProvider = Staking;
type ValidatorProvider = Elections;
type ValidatorRewardsHandler = Staking;
type ValidatorExtractor = Staking;
type FinalityCommitteeManager = Phron;
type SessionPeriod = SessionPeriod;
}
impl pallet_timestamp::Config for Runtime {
type Moment = u64;
#[cfg(not(feature = "runtime-benchmarks"))]
type OnTimestampSet = Aura;
#[cfg(feature = "runtime-benchmarks")]
type OnTimestampSet = ();
type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>;
type WeightInfo = pallet_timestamp::weights::SubstrateWeight<Runtime>;
}
pub const EXISTENTIAL_DEPOSIT: u128 = phronesis::PHRON;
impl pallet_balances::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
type Balance = Balance;
type DustRemoval = ();
type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
type AccountStore = System;
type ReserveIdentifier = [u8; 8];
type RuntimeHoldReason = RuntimeHoldReason;
type FreezeIdentifier = ();
type MaxLocks = ConstU32<50>;
type MaxReserves = ();
type MaxHolds = ();
type MaxFreezes = ();
}
impl pallet_nicks::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type ReservationFee = ConstU128<1_000>;
type Slashed = ();
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type MinLength = ConstU32<5>;
type MaxLength = ConstU32<40>;
}
parameter_types! {
pub const SubAccountDeposit: Balance = phronesis::PHRON;
pub const BasicDeposit: Balance = phronesis::deposit(1, 17);
pub const FieldDeposit: Balance = phronesis::deposit(0, 1);
}
impl pallet_identity::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Currency = Balances;
type BasicDeposit = BasicDeposit;
type FieldDeposit = FieldDeposit;
type SubAccountDeposit = SubAccountDeposit;
type MaxSubAccounts = ConstU32<60>;
type MaxAdditionalFields = ConstU32<60>;
type MaxRegistrars = ConstU32<15>;
type Slashed = Treasury;
type ForceOrigin = frame_system::EnsureRoot<AccountId>;
type RegistrarOrigin = frame_system::EnsureRoot<AccountId>;
type WeightInfo = pallet_identity::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const TransactionByteFee: Balance = phronesis::TRANSACTION_BYTE_FEE;
pub const TargetBlockFullness: sp_runtime::Perquintill = sp_runtime::Perquintill::from_percent(25);
pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(4, 1_000);
pub MinimumMultiplier: Multiplier = Multiplier::from(1u128);
pub MaximumMultiplier: Multiplier = Multiplier::from(100_000u128);
}
pub struct LengthToFee;
#[cfg_attr(coverage_nightly, coverage(off))]
impl frame_support::weights::WeightToFeePolynomial for LengthToFee {
type Balance = Balance;
fn polynomial() -> frame_support::weights::WeightToFeeCoefficients<Self::Balance> {
smallvec::smallvec![
frame_support::weights::WeightToFeeCoefficient {
degree: 1,
coeff_frac: sp_runtime::Perbill::zero(),
coeff_integer: phronesis::TRANSACTION_BYTE_FEE,
negative: false,
},
frame_support::weights::WeightToFeeCoefficient {
degree: 3,
coeff_frac: sp_runtime::Perbill::zero(),
coeff_integer: phronesis::SUPPLY_FACTOR,
negative: false,
},
]
}
}
type NegativeImbalance = <Balances as Currency<AccountId>>::NegativeImbalance;
pub struct EverythingToTheTreasury;
#[cfg_attr(coverage_nightly, coverage(off))]
impl OnUnbalanced<NegativeImbalance> for EverythingToTheTreasury {
fn on_unbalanceds<B>(mut fees_then_tips: impl Iterator<Item = NegativeImbalance>) {
if let Some(fees) = fees_then_tips.next() {
Treasury::on_unbalanced(fees);
if let Some(tips) = fees_then_tips.next() {
Treasury::on_unbalanced(tips);
}
}
}
}
pub struct DealWithFees<R>(core::marker::PhantomData<R>);
#[cfg_attr(coverage_nightly, coverage(off))]
impl<R> frame_support::traits::OnUnbalanced<pallet_balances::NegativeImbalance<R>>
for DealWithFees<R>
where
R: pallet_authorship::Config + pallet_balances::Config,
{
fn on_unbalanceds<B>(
mut fees_then_tips: impl Iterator<Item = pallet_balances::NegativeImbalance<R>>,
) {
if fees_then_tips.next().is_some() {
if let Some(tips) = fees_then_tips.next() {
if let Some(author) = <pallet_authorship::Pallet<R>>::author() {
<pallet_balances::Pallet<R>>::resolve_creating(&author, tips);
}
}
}
}
}
impl pallet_transaction_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type OnChargeTransaction = CurrencyAdapter<Balances, DealWithFees<Runtime>>;
type OperationalFeeMultiplier = ConstU8<5>;
type WeightToFee =
frame_support::weights::ConstantMultiplier<Balance, ConstU128<{ phronesis::WEIGHT_FEE }>>;
type LengthToFee = LengthToFee;
type FeeMultiplierUpdate = pallet_transaction_payment::TargetedFeeAdjustment<
Self,
TargetBlockFullness,
AdjustmentVariable,
MinimumMultiplier,
MaximumMultiplier,
>;
}
impl pallet_sudo::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type RuntimeCall = RuntimeCall;
type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const Offset: u32 = 0;
pub const SessionPeriod: u32 = DEFAULT_SESSION_PERIOD;
}
pub struct IdentityValidator;
#[cfg_attr(coverage_nightly, coverage(off))]
impl<T> traits::Convert<T, Option<T>> for IdentityValidator {
fn convert(t: T) -> Option<T> {
Some(t)
}
}
impl pallet_session::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type ValidatorId = <Self as frame_system::Config>::AccountId;
type ValidatorIdOf = IdentityValidator;
type ShouldEndSession = pallet_session::PeriodicSessions<SessionPeriod, Offset>;
type NextSessionRotation = pallet_session::PeriodicSessions<SessionPeriod, Offset>;
type SessionManager = Phron;
type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
type Keys = SessionKeys;
type WeightInfo = pallet_session::weights::SubstrateWeight<Runtime>;
}
impl pallet_session::historical::Config for Runtime {
type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
}
pub struct StakingBenchmarkingConfig;
impl pallet_staking::BenchmarkingConfig for StakingBenchmarkingConfig {
type MaxValidators = ConstU32<1_000>;
type MaxNominators = ConstU32<1_000>;
}
pallet_staking_reward_curve::build! {
const REWARD_CURVE: sp_runtime::curve::PiecewiseLinear<'static> = curve!(
min_inflation: 0_025_000,
max_inflation: 0_100_000,
ideal_stake: 0_500_000,
falloff: 0_050_000,
max_piece_count: 40,
test_precision: 0_005_000,
);
}
parameter_types! {
pub const SessionsPerEra: sp_staking::EraIndex = DEFAULT_SESSIONS_PER_ERA;
pub const BondingDuration: sp_staking::EraIndex = 24 * 28;
pub const SlashDeferDuration: sp_staking::EraIndex = 22 * 28;
pub const RewardCurve: &'static sp_runtime::curve::PiecewiseLinear<'static> = &REWARD_CURVE;
pub const OffendngValidatorsThreshold: sp_runtime::Perbill = sp_runtime::Perbill::from_percent(17);
pub OffchainRepeat: BlockNumber = 5;
}
const MAX_NOMINATIONS: u32 = 1;
impl pallet_staking::Config for Runtime {
type Currency = Balances;
type CurrencyBalance = Balance;
type UnixTime = Timestamp;
type CurrencyToVote = sp_staking::currency_to_vote::U128CurrencyToVote;
type ElectionProvider = Elections;
type GenesisElectionProvider = Elections;
type NominationsQuota = pallet_staking::FixedNominationsQuota<MAX_NOMINATIONS>;
type HistoryDepth = ConstU32<100>;
type RewardRemainder = Treasury;
type RuntimeEvent = RuntimeEvent;
type Slash = Treasury;
type Reward = ();
type SessionsPerEra = SessionsPerEra;
type BondingDuration = BondingDuration;
type SlashDeferDuration = SlashDeferDuration;
type AdminOrigin = frame_system::EnsureRoot<AccountId>;
type SessionInterface = Self;
type EraPayout = pallet_staking::ConvertCurve<RewardCurve>;
type NextNewSession = Session;
type MaxNominatorRewardedPerValidator = ConstU32<100>;
type OffendingValidatorsThreshold = OffendngValidatorsThreshold;
type VoterList = pallet_staking::UseNominatorsAndValidatorsMap<Runtime>;
type TargetList = pallet_staking::UseValidatorsMap<Self>;
type MaxUnlockingChunks = ConstU32<16>;
type EventListeners = ();
type BenchmarkingConfig = StakingBenchmarkingConfig;
type WeightInfo = pallet_staking::weights::SubstrateWeight<Runtime>;
}
parameter_types! {
pub const ProposalBond: Permill = Permill::from_percent(5);
pub const ProposalBondMinimum: Balance = 10 * phronesis::PHRON;
pub const SpendPeriod: BlockNumber = 2 * HOURS;
pub const Burn: Permill = Permill::from_percent(0);
pub const TreasuryPalletId: frame_support::PalletId = frame_support::PalletId(*b"ph/trsry");
pub const MaxBalance: Balance = Balance::MAX;
}
pub struct TreasuryGovernance;
#[cfg_attr(coverage_nightly, coverage(off))]
impl frame_support::traits::SortedMembers<AccountId> for TreasuryGovernance {
fn sorted_members() -> Vec<AccountId> {
pallet_sudo::Pallet::<Runtime>::key().into_iter().collect()
}
}
impl pallet_treasury::Config for Runtime {
type Currency = Balances;
type ApproveOrigin = frame_system::EnsureSignedBy<TreasuryGovernance, AccountId>;
type RejectOrigin = frame_system::EnsureSignedBy<TreasuryGovernance, AccountId>;
type RuntimeEvent = RuntimeEvent;
type OnSlash = ();
type ProposalBond = ProposalBond;
type ProposalBondMinimum = ProposalBondMinimum;
type ProposalBondMaximum = ();
type SpendPeriod = SpendPeriod;
type Burn = Burn;
type PalletId = TreasuryPalletId;
type BurnDestination = ();
type WeightInfo = pallet_treasury::weights::SubstrateWeight<Runtime>;
type SpendFunds = ();
type MaxApprovals = ConstU32<100>;
type SpendOrigin =
frame_system::EnsureWithSuccess<frame_system::EnsureRoot<AccountId>, AccountId, MaxBalance>;
}
parameter_types! {
pub const PostBlockAndTxnHashes: pallet_ethereum::PostLogContent = pallet_ethereum::PostLogContent::BlockAndTxnHashes;
}
impl pallet_ethereum::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type StateRoot = pallet_ethereum::IntermediateStateRoot<Self>;
type PostLogContent = PostBlockAndTxnHashes;
type ExtraDataLength = ConstU32<64>;
}
const BLOCK_GAS_LIMIT: u64 = 20_000_000;
pub const GAS_PER_SECOND: u64 = 50_000_000;
pub const WEIGHT_PER_GAS: u64 = WEIGHT_REF_TIME_PER_SECOND.saturating_div(GAS_PER_SECOND);
parameter_types! {
pub BlockGasLimit: sp_core::U256 = sp_core::U256::from(
NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT.ref_time() / WEIGHT_PER_GAS
);
pub PrecompilesValue: FrontierPrecompiles<Runtime> = FrontierPrecompiles::<_>::new();
pub WeightPerGas: frame_support::weights::Weight = frame_support::weights::Weight::from_parts(
WEIGHT_PER_GAS,
0
);
pub BlockPovSizeLimit: u64 = NORMAL_DISPATCH_RATIO * MAX_BLOCK_SIZE as u64;
pub GasLimitPovSizeRatio: u64 = BLOCK_GAS_LIMIT.saturating_div(BlockPovSizeLimit::get()).saturating_add(1);
}
pub struct TransactionPaymentGasPrice;
#[cfg_attr(coverage_nightly, coverage(off))]
impl pallet_evm::FeeCalculator for TransactionPaymentGasPrice {
fn min_gas_price() -> (sp_core::U256, frame_support::weights::Weight) {
(
TransactionPayment::next_fee_multiplier()
.saturating_mul_int::<Balance>(
phronesis::WEIGHT_FEE.saturating_mul(WEIGHT_PER_GAS as u128),
)
.into(),
<Runtime as frame_system::Config>::DbWeight::get().reads(1),
)
}
}
pub struct PhronFindAuthor<F>(PhantomData<F>);
impl<F: FindAuthor<AccountId>> FindAuthor<sp_core::H160> for PhronFindAuthor<F> {
fn find_author<'a, I>(digests: I) -> Option<sp_core::H160>
where
I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>,
{
F::find_author(digests).map(Into::into)
}
}
impl_on_charge_evm_transaction!();
impl pallet_evm::Config for Runtime {
type FeeCalculator = TransactionPaymentGasPrice;
type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
type WeightPerGas = WeightPerGas;
type BlockHashMapping = pallet_ethereum::EthereumBlockHashMapping<Self>;
type CallOrigin = pallet_evm::EnsureAddressRoot<AccountId>;
type WithdrawOrigin = pallet_evm::EnsureAddressNever<AccountId>;
type AddressMapping = pallet_evm::IdentityAddressMapping;
type Currency = Balances;
type RuntimeEvent = RuntimeEvent;
type PrecompilesType = FrontierPrecompiles<Self>;
type PrecompilesValue = PrecompilesValue;
type ChainId = ConstU64<4477>;
type BlockGasLimit = BlockGasLimit;
type Runner = pallet_evm::runner::stack::Runner<Self>;
type OnChargeTransaction = OnChargeEVMTransaction<DealWithFees<Runtime>>;
type OnCreate = ();
type FindAuthor = PhronFindAuthor<pallet_session::FindAccountFromAuthorIndex<Self, Aura>>;
type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
type Timestamp = Timestamp;
type WeightInfo = pallet_evm::weights::SubstrateWeight<Self>;
}
parameter_types! {
pub GasPriceBoundDivisor: U256 = U256::from(1024);
pub DefaultBaseFeePerGas: U256 = U256::from(1_000_000_000u64);
pub DefaultElasticity: Permill = Permill::from_parts(125_000);
}
impl pallet_dynamic_fee::Config for Runtime {
type MinGasPriceBoundDivisor = GasPriceBoundDivisor;
}
pub struct BaseFeeThreshold;
#[cfg_attr(coverage_nightly, coverage(off))]
impl pallet_base_fee::BaseFeeThreshold for BaseFeeThreshold {
fn lower() -> Permill {
Permill::zero()
}
fn ideal() -> Permill {
Permill::from_parts(500_000)
}
fn upper() -> Permill {
Permill::from_parts(1_000_000)
}
}
impl pallet_base_fee::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Threshold = BaseFeeThreshold;
type DefaultBaseFeePerGas = DefaultBaseFeePerGas;
type DefaultElasticity = DefaultElasticity;
}
impl frame_system::offchain::SigningTypes for Runtime {
type Public = <Signature as sp_runtime::traits::Verify>::Signer;
type Signature = Signature;
}
impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
where
RuntimeCall: From<C>,
{
type Extrinsic = UncheckedExtrinsic;
type OverarchingCall = RuntimeCall;
}
impl<LocalCall> frame_system::offchain::CreateSignedTransaction<LocalCall> for Runtime
where
RuntimeCall: From<LocalCall>,
{
fn create_transaction<C: frame_system::offchain::AppCrypto<Self::Public, Self::Signature>>(
call: RuntimeCall,
public: <Signature as sp_runtime::traits::Verify>::Signer,
account: AccountId,
index: Index,
) -> Option<(
RuntimeCall,
<UncheckedExtrinsic as sp_runtime::traits::Extrinsic>::SignaturePayload,
)> {
let signed_extra: SignedExtra = (
frame_system::CheckNonZeroSender::<Runtime>::new(),
frame_system::CheckSpecVersion::<Runtime>::new(),
frame_system::CheckTxVersion::<Runtime>::new(),
frame_system::CheckGenesis::<Runtime>::new(),
frame_system::CheckEra::<Runtime>::from(sp_runtime::generic::Era::mortal(
BlockHashCount::get() as u64,
System::block_number().saturated_into::<u64>().saturating_sub(1),
)),
frame_system::CheckNonce::<Runtime>::from(index),
frame_system::CheckWeight::<Runtime>::new(),
pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(0),
);
let raw_payload = SignedPayload::new(call, signed_extra)
.map_err(|e| {
log::error!("Error creating signed payload: {:?}", e);
})
.ok()?;
let signature = raw_payload.using_encoded(|payload| C::sign(payload, public))?;
let address = account;
let (call, extra, _) = raw_payload.deconstruct();
Some((call, (address, signature, extra)))
}
}
construct_runtime!(
pub struct Runtime {
System: frame_system,
Aura: pallet_aura,
Timestamp: pallet_timestamp,
Balances: pallet_balances,
TransactionPayment: pallet_transaction_payment,
Nicks: pallet_nicks,
Identity: pallet_identity,
Authorship: pallet_authorship,
Staking: pallet_staking,
Historical: pallet_session_historical,
Session: pallet_session,
Phron: pallet_phron,
Elections: pallet_elections,
Treasury: pallet_treasury,
CommitteeManagement: pallet_committee_management,
Sudo: pallet_sudo,
EVM: pallet_evm,
Ethereum: pallet_ethereum,
BaseFee: pallet_base_fee,
DynamicFee: pallet_dynamic_fee,
}
);
impl fp_self_contained::SelfContainedCall for RuntimeCall {
type SignedInfo = sp_core::H160;
fn is_self_contained(&self) -> bool {
match self {
RuntimeCall::Ethereum(call) => call.is_self_contained(),
_ => false,
}
}
fn check_self_contained(
&self,
) -> Option<Result<Self::SignedInfo, sp_runtime::transaction_validity::TransactionValidityError>>
{
match self {
RuntimeCall::Ethereum(call) => call.check_self_contained(),
_ => None,
}
}
fn validate_self_contained(
&self,
info: &Self::SignedInfo,
dispatch_info: &sp_runtime::traits::DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<sp_runtime::transaction_validity::TransactionValidity> {
match self {
RuntimeCall::Ethereum(call) => call.validate_self_contained(info, dispatch_info, len),
_ => None,
}
}
fn pre_dispatch_self_contained(
&self,
info: &Self::SignedInfo,
dispatch_info: &sp_runtime::traits::DispatchInfoOf<RuntimeCall>,
len: usize,
) -> Option<Result<(), sp_runtime::transaction_validity::TransactionValidityError>> {
match self {
RuntimeCall::Ethereum(call) =>
call.pre_dispatch_self_contained(info, dispatch_info, len),
_ => None,
}
}
fn apply_self_contained(
self,
info: Self::SignedInfo,
) -> Option<sp_runtime::DispatchResultWithInfo<sp_runtime::traits::PostDispatchInfoOf<Self>>> {
use sp_runtime::traits::Dispatchable;
match self {
call @ RuntimeCall::Ethereum(pallet_ethereum::Call::transact { .. }) =>
Some(call.dispatch(RuntimeOrigin::from(
pallet_ethereum::RawOrigin::EthereumTransaction(info),
))),
_ => None,
}
}
}
pub type Address = AccountId;
pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
pub type Block = generic::Block<Header, UncheckedExtrinsic>;
pub type SignedBlock = generic::SignedBlock<Block>;
pub type BlockId = generic::BlockId<Block>;
pub type SignedExtra = (
frame_system::CheckNonZeroSender<Runtime>,
frame_system::CheckSpecVersion<Runtime>,
frame_system::CheckTxVersion<Runtime>,
frame_system::CheckGenesis<Runtime>,
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
);
pub type UncheckedExtrinsic =
fp_self_contained::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
pub type CheckedExtrinsic =
fp_self_contained::CheckedExtrinsic<AccountId, RuntimeCall, SignedExtra, sp_core::H160>;
pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
pub type Executive = frame_executive::Executive<
Runtime,
Block,
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
OnRuntimeUpgrade,
>;
pub struct OnRuntimeUpgrade;
impl frame_support::traits::OnRuntimeUpgrade for OnRuntimeUpgrade {
fn on_runtime_upgrade() -> Weight {
[
("0xf24FF3a9CF04c71Dbc94D0b566f7A27B94566cac", b"phronrun"),
("0xC8742A5fBb4e5db67c50d326Ee7F7b846A842642", b"phronrun"),
]
.iter()
.for_each(|(address, lock_id)| {
if let Ok(address) = array_bytes::hex_n_into::<_, AccountId, 20>(address) {
<pallet_balances::Locks<Runtime>>::mutate(address, |locks| {
locks.retain(|lock| &lock.id != *lock_id);
});
}
});
frame_support::weights::Weight::zero()
}
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
Ok(Vec::new())
}
#[cfg(feature = "try-runtime")]
fn post_upgrade(_state: Vec<u8>) -> Result<(), sp_runtime::DispatchError> {
Ok(())
}
}
#[cfg(feature = "runtime-benchmarks")]
use frame_benchmarking::baseline::Pallet as BaselineBench;
#[cfg(feature = "runtime-benchmarks")]
use frame_system_benchmarking::Pallet as SystemBench;
#[cfg(feature = "runtime-benchmarks")]
mod benches {
frame_benchmarking::define_benchmarks!(
[frame_benchmarking, BaselineBench::<Runtime>]
[frame_system, SystemBench::<Runtime>]
[pallet_balances, Balances]
[pallet_timestamp, Timestamp]
[pallet_sudo, Sudo]
[pallet_evm, EVM]
);
}
impl_runtime_apis! {
impl core_primitives::PhronSessionApi<Block> for Runtime {
fn millisecs_per_block() -> u64 {
MILLISECS_PER_BLOCK
}
fn session_period() -> u32 {
SessionPeriod::get()
}
fn authorities() -> Vec<PhronId> {
Phron::authorities()
}
fn next_session_authorities() -> Result<Vec<PhronId>, PhronApiError> {
let next_authorities = Phron::next_authorities();
if next_authorities.is_empty() {
return Err(PhronApiError::DecodeKey)
}
Ok(next_authorities)
}
fn authority_data() -> SessionAuthorityData {
SessionAuthorityData::new(Phron::authorities(), Phron::emergency_finalizer())
}
fn next_session_authority_data() -> Result<SessionAuthorityData, PhronApiError> {
Ok(SessionAuthorityData::new(
Self::next_session_authorities()?,
Phron::queued_emergency_finalizer(),
))
}
fn finality_version() -> FinalityVersion {
Phron::finality_version()
}
fn next_session_finality_version() -> FinalityVersion {
Phron::next_session_finality_version()
}
fn next_session_aura_authorities() -> Vec<AuraId> {
let queued_keys = pallet_session::QueuedKeys::<Runtime>::get();
queued_keys.into_iter().filter_map(|(_, keys)| keys.get(sp_application_crypto::key_types::AURA)).collect()
}
fn key_owner(key: PhronId) -> Option<AccountId> {
Session::key_owner(core_primitives::KEY_TYPE, key.as_ref())
}
}
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
}
fn execute_block(block: Block) {
Executive::execute_block(block);
}
fn initialize_block(header: &<Block as BlockT>::Header) {
Executive::initialize_block(header)
}
}
impl sp_api::Metadata<Block> for Runtime {
fn metadata() -> OpaqueMetadata {
OpaqueMetadata::new(Runtime::metadata().into())
}
fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
Runtime::metadata_at_version(version)
}
fn metadata_versions() -> sp_std::vec::Vec<u32> {
Runtime::metadata_versions()
}
}
impl sp_block_builder::BlockBuilder<Block> for Runtime {
fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
Executive::apply_extrinsic(extrinsic)
}
fn finalize_block() -> <Block as BlockT>::Header {
Executive::finalize_block()
}
fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
data.create_extrinsics()
}
fn check_inherents(
block: Block,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
}
}
impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
fn validate_transaction(
source: TransactionSource,
xt: <Block as BlockT>::Extrinsic,
block_hash: <Block as BlockT>::Hash,
) -> TransactionValidity {
Executive::validate_transaction(source, xt, block_hash)
}
}
impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
fn offchain_worker(header: &<Block as BlockT>::Header) {
Executive::offchain_worker(header)
}
}
impl fp_rpc::EthereumRuntimeRPCApi<Block> for Runtime {
fn chain_id() -> u64 {
<<Runtime as pallet_evm::Config>::ChainId as sp_core::Get<u64>>::get()
}
fn account_basic(address: sp_core::H160) -> pallet_evm::Account {
let (account, _) = EVM::account_basic(&address);
account
}
fn gas_price() -> sp_core::U256 {
use pallet_evm::FeeCalculator;
let (gas_price, _) = <Runtime as pallet_evm::Config>::FeeCalculator::min_gas_price();
gas_price
}
fn account_code_at(address: sp_core::H160) -> Vec<u8> {
pallet_evm::AccountCodes::<Runtime>::get(address)
}
fn author() -> sp_core::H160 {
<pallet_evm::Pallet<Runtime>>::find_author()
}
fn storage_at(address: sp_core::H160, index: sp_core::U256) -> sp_core::H256 {
let mut tmp = [0u8; 32];
index.to_big_endian(&mut tmp);
pallet_evm::AccountStorages::<Runtime>::get(address, sp_core::H256::from_slice(&tmp[..]))
}
fn call(
from: sp_core::H160,
to: sp_core::H160,
data: Vec<u8>,
value: sp_core::U256,
gas_limit: sp_core::U256,
max_fee_per_gas: Option<sp_core::U256>,
max_priority_fee_per_gas: Option<sp_core::U256>,
nonce: Option<sp_core::U256>,
estimate: bool,
access_list: Option<Vec<(sp_core::H160, Vec<sp_core::H256>)>>,
) -> Result<pallet_evm::CallInfo, sp_runtime::DispatchError> {
use pallet_evm::{Runner, GasWeightMapping};
use sp_runtime::traits::UniqueSaturatedInto;
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
#[allow(clippy::or_fun_call)]
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
let transaction_data = TransactionData::new(
pallet_ethereum::TransactionAction::Call(to),
data.clone(),
nonce.unwrap_or_default(),
gas_limit,
None,
max_fee_per_gas,
max_priority_fee_per_gas,
value,
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
access_list.clone().unwrap_or_default(),
);
let without_base_extrinsic_weight = true;
let (weight_limit, proof_size_base_cost) =
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
transaction_data.gas_limit.unique_saturated_into(),
without_base_extrinsic_weight
) {
weight_limit if weight_limit.proof_size() > 0 => {
(Some(weight_limit), Some(transaction_data.proof_size_base_cost.unwrap_or_default()))
}
_ => (None, None),
};
<Runtime as pallet_evm::Config>::Runner::call(
from,
to,
data,
value,
gas_limit.unique_saturated_into(),
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
evm_config,
).map_err(|err| err.error.into())
}
fn create(
from: sp_core::H160,
data: Vec<u8>,
value: sp_core::U256,
gas_limit: sp_core::U256,
max_fee_per_gas: Option<sp_core::U256>,
max_priority_fee_per_gas: Option<sp_core::U256>,
nonce: Option<sp_core::U256>,
estimate: bool,
access_list: Option<Vec<(sp_core::H160, Vec<sp_core::H256>)>>,
) -> Result<pallet_evm::CreateInfo, sp_runtime::DispatchError> {
use pallet_evm::{Runner, GasWeightMapping};
use sp_runtime::traits::UniqueSaturatedInto;
let config = if estimate {
let mut config = <Runtime as pallet_evm::Config>::config().clone();
config.estimate = true;
Some(config)
} else {
None
};
let is_transactional = false;
let validate = true;
#[allow(clippy::or_fun_call)]
let evm_config = config.as_ref().unwrap_or(<Runtime as pallet_evm::Config>::config());
let transaction_data = TransactionData::new(
pallet_ethereum::TransactionAction::Create,
data.clone(),
nonce.unwrap_or_default(),
gas_limit,
None,
max_fee_per_gas,
max_priority_fee_per_gas,
value,
Some(<Runtime as pallet_evm::Config>::ChainId::get()),
access_list.clone().unwrap_or_default(),
);
let without_base_extrinsic_weight = true;
let (weight_limit, proof_size_base_cost) =
match <Runtime as pallet_evm::Config>::GasWeightMapping::gas_to_weight(
transaction_data.gas_limit.unique_saturated_into(),
without_base_extrinsic_weight
) {
weight_limit if weight_limit.proof_size() > 0 => {
(Some(weight_limit),
Some(transaction_data.proof_size_base_cost.unwrap_or_default()))
}
_ => (None, None),
};
<Runtime as pallet_evm::Config>::Runner::create(
from,
data,
value,
gas_limit.unique_saturated_into(),
max_fee_per_gas,
max_priority_fee_per_gas,
nonce,
access_list.unwrap_or_default(),
is_transactional,
validate,
weight_limit,
proof_size_base_cost,
evm_config,
).map_err(|err| err.error.into())
}
fn current_transaction_statuses() -> Option<Vec<fp_rpc::TransactionStatus>> {
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
}
fn current_block() -> Option<pallet_ethereum::Block> {
pallet_ethereum::CurrentBlock::<Runtime>::get()
}
fn current_receipts() -> Option<Vec<pallet_ethereum::Receipt>> {
pallet_ethereum::CurrentReceipts::<Runtime>::get()
}
fn current_all() -> (
Option<pallet_ethereum::Block>,
Option<Vec<pallet_ethereum::Receipt>>,
Option<Vec<fp_rpc::TransactionStatus>>
) {
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentReceipts::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
fn extrinsic_filter(
xts: Vec<<Block as sp_runtime::traits::Block>::Extrinsic>,
) -> Vec<pallet_ethereum::Transaction> {
xts.into_iter().filter_map(|xt| match xt.0.function {
RuntimeCall::Ethereum(
pallet_ethereum::Call::<Runtime>::transact { transaction }
) => Some(transaction),
_ => None
}).collect::<Vec<pallet_ethereum::Transaction>>()
}
fn elasticity() -> Option<Permill> {
None
}
fn gas_limit_multiplier_support() {
}
fn pending_block(
xts: Vec<<Block as sp_runtime::traits::Block>::Extrinsic>,
) -> (Option<pallet_ethereum::Block>, Option<Vec<fp_rpc::TransactionStatus>>) {
use frame_support::traits::OnFinalize;
for ext in xts.into_iter() {
let _ = Executive::apply_extrinsic(ext);
}
Ethereum::on_finalize(System::block_number() + 1);
(
pallet_ethereum::CurrentBlock::<Runtime>::get(),
pallet_ethereum::CurrentTransactionStatuses::<Runtime>::get()
)
}
}
impl fp_rpc::ConvertTransactionRuntimeApi<Block> for Runtime {
fn convert_transaction(
transaction: pallet_ethereum::Transaction
) -> <Block as sp_runtime::traits::Block>::Extrinsic {
UncheckedExtrinsic::new_unsigned(
pallet_ethereum::Call::<Runtime>::transact { transaction }.into(),
)
}
}
impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {
fn slot_duration() -> sp_consensus_aura::SlotDuration {
sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration())
}
fn authorities() -> Vec<AuraId> {
Aura::authorities().into_inner()
}
}
impl sp_session::SessionKeys<Block> for Runtime {
fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
opaque::SessionKeys::generate(seed)
}
fn decode_session_keys(
encoded: Vec<u8>,
) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
}
}
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
fn account_nonce(account: AccountId) -> Nonce {
System::account_nonce(account)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_info(uxt, len)
}
fn query_fee_details(
uxt: <Block as BlockT>::Extrinsic,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_fee_details(uxt, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall>
for Runtime
{
fn query_call_info(
call: RuntimeCall,
len: u32,
) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
TransactionPayment::query_call_info(call, len)
}
fn query_call_fee_details(
call: RuntimeCall,
len: u32,
) -> pallet_transaction_payment::FeeDetails<Balance> {
TransactionPayment::query_call_fee_details(call, len)
}
fn query_weight_to_fee(weight: Weight) -> Balance {
TransactionPayment::weight_to_fee(weight)
}
fn query_length_to_fee(length: u32) -> Balance {
TransactionPayment::length_to_fee(length)
}
}
#[cfg(feature = "runtime-benchmarks")]
impl frame_benchmarking::Benchmark<Block> for Runtime {
fn benchmark_metadata(extra: bool) -> (
Vec<frame_benchmarking::BenchmarkList>,
Vec<frame_support::traits::StorageInfo>,
) {
use frame_benchmarking::{Benchmarking, BenchmarkList};
use frame_support::traits::StorageInfoTrait;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
let storage_info = AllPalletsWithSystem::storage_info();
(list, storage_info)
}
fn dispatch_benchmark(
config: frame_benchmarking::BenchmarkConfig
) -> Result<Vec<frame_benchmarking::BenchmarkBatch>, sp_runtime::RuntimeString> {
use frame_benchmarking::{Benchmarking, BenchmarkBatch};
use sp_storage::TrackedStorageKey;
impl frame_system_benchmarking::Config for Runtime {}
impl frame_benchmarking::baseline::Config for Runtime {}
use frame_support::traits::WhitelistedStorageKeys;
let whitelist: Vec<TrackedStorageKey> = AllPalletsWithSystem::whitelisted_storage_keys();
let mut batches = Vec::<BenchmarkBatch>::new();
let params = (&config, &whitelist);
add_benchmarks!(params, batches);
if batches.is_empty() {
return Err("Benchmark not found for this pallet.".into())
}
Ok(batches)
}
}
#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) {
let weight = Executive::try_runtime_upgrade(checks).map_err(|err| {
log::info!("on_runtime_upgrade failed: {:?}", err);
err
}).unwrap();
(weight, BlockWeights::get().max_block)
}
fn execute_block(
block: Block,
state_root_check: bool,
signature_check: bool,
select: frame_try_runtime::TryStateSelect
) -> Weight {
Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed")
}
}
}