Skip to main content

revive_env/
runtime.rs

1//! Dummy runtime with pallet revive and all necessary pallets for running tests with forge.
2//!
3//! THIS IS WORK IN PROGRESS. It is not yet complete and may change in the future.
4
5use frame_support::{runtime, traits::FindAuthor, weights::constants::WEIGHT_REF_TIME_PER_SECOND};
6use polkadot_sdk::{
7    frame_support::weights::constants::{BlockExecutionWeight, ExtrinsicBaseWeight},
8    pallet_revive::{
9        AccountId32Mapper, BlockWeights,
10        evm::{
11            fees::{BlockRatioFee, Info},
12            runtime::EthExtra,
13        },
14    },
15    pallet_transaction_payment::{ConstFeeMultiplier, Multiplier},
16    parachains_common::{AccountId, Hash, Nonce},
17    polkadot_sdk_frame::runtime::prelude::*,
18    sp_runtime::{AccountId32, generic},
19    sp_weights::ConstantMultiplier,
20    *,
21};
22
23pub type Balance = u128;
24pub type Block = sp_runtime::generic::Block<generic::Header<u64, BlakeTwo256>, UncheckedExtrinsic>;
25pub type UncheckedExtrinsic =
26    pallet_revive::evm::runtime::UncheckedExtrinsic<Address, Signature, EthExtraImpl>;
27
28pub mod currency {
29    use super::Balance;
30    pub const DOLLARS: Balance = 1_000_000_000_000;
31    pub const CENTS: Balance = DOLLARS / 100;
32    pub const MILLICENTS: Balance = CENTS / 1_000;
33}
34
35parameter_types! {
36    pub const TransactionByteFee: Balance = 10 * currency::MILLICENTS;
37    pub FeeMultiplier: Multiplier = Multiplier::one();
38}
39
40// Implements the types required for the transaction payment pallet.
41#[derive_impl(pallet_transaction_payment::config_preludes::TestDefaultConfig)]
42impl pallet_transaction_payment::Config for Runtime {
43    type OnChargeTransaction = pallet_transaction_payment::FungibleAdapter<Balances, ()>;
44    type WeightToFee = BlockRatioFee<1, 1, Self, Balance>;
45    type LengthToFee = ConstantMultiplier<Balance, TransactionByteFee>;
46    type FeeMultiplierUpdate = ConstFeeMultiplier<FeeMultiplier>;
47}
48
49#[runtime]
50mod runtime {
51    #[runtime::runtime]
52    #[runtime::derive(
53        RuntimeCall,
54        RuntimeEvent,
55        RuntimeError,
56        RuntimeOrigin,
57        RuntimeFreezeReason,
58        RuntimeHoldReason,
59        RuntimeSlashReason,
60        RuntimeLockId,
61        RuntimeTask,
62        RuntimeViewFunction
63    )]
64    pub struct Runtime;
65
66    #[runtime::pallet_index(0)]
67    pub type System = frame_system;
68
69    #[runtime::pallet_index(1)]
70    pub type Timestamp = pallet_timestamp;
71
72    #[runtime::pallet_index(2)]
73    pub type Balances = pallet_balances;
74
75    #[runtime::pallet_index(3)]
76    pub type Contracts = pallet_revive;
77    /// Provides the ability to charge for extrinsic execution.
78    #[runtime::pallet_index(4)]
79    pub type TransactionPayment = pallet_transaction_payment::Pallet<Runtime>;
80}
81
82#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
83impl frame_system::Config for Runtime {
84    type Block = Block;
85    type AccountId = AccountId;
86    type Hash = Hash;
87    type Nonce = Nonce;
88    type AccountData = pallet_balances::AccountData<<Self as pallet_balances::Config>::Balance>;
89}
90
91#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
92impl pallet_balances::Config for Runtime {
93    type AccountStore = System;
94    type Balance = Balance;
95    type ExistentialDeposit = ConstU128<1_000>;
96}
97
98#[derive_impl(pallet_timestamp::config_preludes::TestDefaultConfig)]
99impl pallet_timestamp::Config for Runtime {}
100
101/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
102/// This is used to limit the maximal weight of a single extrinsic.
103#[allow(unused)]
104const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
105/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used
106/// by  Operational  extrinsics.
107#[allow(unused)]
108const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
109/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
110#[allow(unused)]
111const MAXIMUM_BLOCK_WEIGHT: Weight =
112    Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
113
114parameter_types! {
115    pub const UnstableInterface: bool = true;
116    pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
117    pub const NativeToEthRatio: u32 = 1_000_000;
118    pub const GasScale : u32 = 1_000_000;
119
120    pub const DepositPerByte: Balance = 1;
121    pub const DepositPerItem: Balance = 2;
122    pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
123    .base_block(BlockExecutionWeight::get())
124    .for_class(DispatchClass::all(), |weights| {
125        weights.base_extrinsic = ExtrinsicBaseWeight::get();
126    })
127    .for_class(DispatchClass::Normal, |weights| {
128        weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
129    })
130    .for_class(DispatchClass::Operational, |weights| {
131        weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
132        // Operational transactions have some extra reserved space, so that they
133        // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
134        weights.reserved = Some(
135            MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
136        );
137    })
138    .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
139    .build_or_panic();
140}
141
142#[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)]
143impl pallet_revive::Config for Runtime {
144    type Time = Timestamp;
145    type Balance = Balance;
146    type Currency = Balances;
147    type DepositPerByte = DepositPerByte;
148    type DepositPerItem = DepositPerItem;
149    type AddressMapper = AccountId32Mapper<Self>;
150    type RuntimeMemory = ConstU32<{ 512 * 1024 * 1024 }>;
151    type PVFMemory = ConstU32<{ 1024 * 1024 * 1024 }>;
152    type UploadOrigin = EnsureSigned<AccountId32>;
153    type InstantiateOrigin = EnsureSigned<AccountId32>;
154    type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
155    type ChainId = ChainId;
156    type NativeToEthRatio = NativeToEthRatio;
157    type FindAuthor = Self;
158    type DebugEnabled = ConstBool<true>;
159    type GasScale = GasScale;
160    type FeeInfo = Info<Address, Signature, EthExtraImpl>;
161}
162
163pub use polkadot_sdk::parachains_common::Signature;
164
165pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
166
167/// The transaction extensions that are added to the runtime.
168type TxExtension = (
169    // Checks that the sender is not the zero address.
170    frame_system::CheckNonZeroSender<Runtime>,
171    // Checks that the runtime version is correct.
172    frame_system::CheckSpecVersion<Runtime>,
173    // Checks that the transaction version is correct.
174    frame_system::CheckTxVersion<Runtime>,
175    // Checks that the genesis hash is correct.
176    frame_system::CheckGenesis<Runtime>,
177    // Checks that the era is valid.
178    frame_system::CheckEra<Runtime>,
179    // Checks that the nonce is valid.
180    frame_system::CheckNonce<Runtime>,
181    // Checks that the weight is valid.
182    frame_system::CheckWeight<Runtime>,
183    // Ensures that the sender has enough funds to pay for the transaction
184    // and deducts the fee from the sender's account.
185    pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
186    // Needs to be done after all extensions that rely on a signed origin.
187    pallet_revive::evm::tx_extension::SetOrigin<Runtime>,
188    // Reclaim the unused weight from the block using post dispatch information.
189    // It must be last in the pipeline in order to catch the refund in previous transaction
190    // extensions
191    frame_system::WeightReclaim<Runtime>,
192);
193/// Default extensions applied to Ethereum transactions.
194#[derive(Clone, PartialEq, Eq, Debug)]
195pub struct EthExtraImpl;
196
197impl EthExtra for EthExtraImpl {
198    type Config = Runtime;
199    type Extension = TxExtension;
200
201    fn get_eth_extension(nonce: u32, tip: Balance) -> Self::Extension {
202        (
203            frame_system::CheckNonZeroSender::<Runtime>::new(),
204            frame_system::CheckSpecVersion::<Runtime>::new(),
205            frame_system::CheckTxVersion::<Runtime>::new(),
206            frame_system::CheckGenesis::<Runtime>::new(),
207            frame_system::CheckMortality::from(sp_runtime::generic::Era::Immortal),
208            frame_system::CheckNonce::<Runtime>::from(nonce),
209            frame_system::CheckWeight::<Runtime>::new(),
210            pallet_transaction_payment::ChargeTransactionPayment::<Runtime>::from(tip),
211            pallet_revive::evm::tx_extension::SetOrigin::<Runtime>::new_from_eth_transaction(),
212            frame_system::WeightReclaim::<Runtime>::new(),
213        )
214    }
215}
216
217impl pallet_revive::evm::runtime::SetWeightLimit for RuntimeCall {
218    fn set_weight_limit(&mut self, new_weight_limit: Weight) -> Weight {
219        use pallet_revive::pallet::Call as ReviveCall;
220        match self {
221            Self::Contracts(
222                ReviveCall::eth_call { weight_limit, .. }
223                | ReviveCall::eth_instantiate_with_code { weight_limit, .. },
224            ) => {
225                let old = *weight_limit;
226                *weight_limit = new_weight_limit;
227                old
228            }
229            _ => Weight::default(),
230        }
231    }
232}
233
234parameter_types! {
235    pub storage ChainId: u64 = 420_420_420;
236    pub storage BlockAuthor: AccountId32 = {
237        [[0xff; 20].as_slice(), [0xee; 12].as_slice()].concat().as_slice().try_into().unwrap()
238    };
239}
240
241impl FindAuthor<<Self as frame_system::Config>::AccountId> for Runtime {
242    fn find_author<'a, I>(_digests: I) -> Option<<Self as frame_system::Config>::AccountId>
243    where
244        I: 'a + IntoIterator<Item = (frame_support::ConsensusEngineId, &'a [u8])>,
245    {
246        Some(BlockAuthor::get())
247    }
248}