contracts_node_runtime/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
3#![recursion_limit = "256"]
4
5// Make the WASM binary available.
6#[cfg(feature = "std")]
7include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
8
9mod assets_config;
10mod contracts_config;
11mod revive_config;
12
13extern crate alloc;
14use alloc::vec::Vec;
15use frame_support::{
16	derive_impl,
17	dispatch::DispatchClass,
18	genesis_builder_helper::{build_state, get_preset},
19};
20use frame_system::limits::{BlockLength, BlockWeights};
21use polkadot_runtime_common::SlowAdjustingFeeUpdate;
22use sp_api::impl_runtime_apis;
23use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
24use sp_runtime::{
25	create_runtime_str, generic, impl_opaque_keys,
26	traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify},
27	transaction_validity::{TransactionSource, TransactionValidity},
28	ApplyExtrinsicResult, MultiSignature,
29};
30#[cfg(feature = "std")]
31use sp_version::NativeVersion;
32use sp_version::RuntimeVersion;
33
34// A few exports that help ease life for downstream crates.
35pub use frame_support::{
36	construct_runtime, parameter_types,
37	traits::{
38		AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32, ConstU8, KeyOwnerProofSystem,
39		Randomness, StorageInfo,
40	},
41	weights::{
42		constants::{
43			BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND,
44		},
45		IdentityFee, Weight,
46	},
47	StorageValue,
48};
49pub use frame_system::Call as SystemCall;
50pub use pallet_balances::Call as BalancesCall;
51pub use pallet_timestamp::Call as TimestampCall;
52use pallet_transaction_payment::FungibleAdapter;
53#[cfg(any(feature = "std", test))]
54pub use sp_runtime::BuildStorage;
55pub use sp_runtime::{Perbill, Permill};
56
57/// An index to a block.
58pub type BlockNumber = u32;
59
60/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
61pub type Signature = MultiSignature;
62
63/// Some way of identifying an account on the chain. We intentionally make it equivalent
64/// to the public key of our transaction signing scheme.
65pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
66
67/// Balance of an account.
68pub type Balance = u128;
69
70/// Index of a transaction in the chain.
71pub type Nonce = u32;
72
73/// A hash of some data used by the chain.
74pub type Hash = sp_core::H256;
75
76/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
77/// the specifics of the runtime. They can then be made to be agnostic over specific formats
78/// of data like extrinsics, allowing for them to continue syncing the network through upgrades
79/// to even the core data structures.
80pub mod opaque {
81	use super::*;
82
83	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;
84
85	/// Opaque block header type.
86	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
87	/// Opaque block type.
88	pub type Block = generic::Block<Header, UncheckedExtrinsic>;
89	/// Opaque block identifier type.
90	pub type BlockId = generic::BlockId<Block>;
91
92	impl_opaque_keys! {
93		pub struct SessionKeys {}
94	}
95}
96// To learn more about runtime versioning, see:
97// https://docs.substrate.io/main-docs/build/upgrade#runtime-versioning
98#[sp_version::runtime_version]
99pub const VERSION: RuntimeVersion = RuntimeVersion {
100	spec_name: create_runtime_str!("substrate-contracts-node"),
101	impl_name: create_runtime_str!("substrate-contracts-node"),
102	authoring_version: 1,
103	// The version of the runtime specification. A full node will not attempt to use its native
104	//   runtime in substitute for the on-chain Wasm runtime unless all of `spec_name`,
105	//   `spec_version`, and `authoring_version` are the same between Wasm and native.
106	// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
107	//   the compatible custom types.
108	spec_version: 100,
109	impl_version: 1,
110	apis: RUNTIME_API_VERSIONS,
111	transaction_version: 1,
112	state_version: 1,
113};
114
115/// The version information used to identify this runtime when compiled natively.
116#[cfg(feature = "std")]
117pub fn native_version() -> NativeVersion {
118	NativeVersion { runtime_version: VERSION, can_author_with: Default::default() }
119}
120
121const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75);
122
123/// We assume that ~10% of the block weight is consumed by `on_initialize` handlers.
124/// This is used to limit the maximal weight of a single extrinsic.
125const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10);
126
127/// We allow for 2 seconds of compute with a 6 second average block time, with maximum proof size.
128const MAXIMUM_BLOCK_WEIGHT: Weight =
129	Weight::from_parts(WEIGHT_REF_TIME_PER_SECOND.saturating_mul(2), u64::MAX);
130
131// Prints debug output of the `revive` pallet to stdout if the node is
132// started with `-lruntime::revive=trace` or `-lruntime::contracts=debug`.
133const CONTRACTS_DEBUG_OUTPUT: pallet_contracts::DebugInfo =
134	pallet_contracts::DebugInfo::UnsafeDebug;
135const CONTRACTS_EVENTS: pallet_contracts::CollectEvents =
136	pallet_contracts::CollectEvents::UnsafeCollect;
137const REVIVE_DEBUG_OUTPUT: pallet_revive::DebugInfo = pallet_revive::DebugInfo::UnsafeDebug;
138const REVIVE_EVENTS: pallet_revive::CollectEvents = pallet_revive::CollectEvents::UnsafeCollect;
139
140// Unit = the base number of indivisible units for balances
141const MILLIUNIT: Balance = 1_000_000_000;
142pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT;
143
144impl pallet_insecure_randomness_collective_flip::Config for Runtime {}
145
146parameter_types! {
147	pub const BlockHashCount: BlockNumber = 2400;
148	pub const Version: RuntimeVersion = VERSION;
149
150	// This part is copied from Substrate's `bin/node/runtime/src/lib.rs`.
151	//  The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the
152	// `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize
153	// the lazy contract deletion.
154	pub RuntimeBlockLength: BlockLength =
155		BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO);
156	pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder()
157		.base_block(BlockExecutionWeight::get())
158		.for_class(DispatchClass::all(), |weights| {
159			weights.base_extrinsic = ExtrinsicBaseWeight::get();
160		})
161		.for_class(DispatchClass::Normal, |weights| {
162			weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT);
163		})
164		.for_class(DispatchClass::Operational, |weights| {
165			weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT);
166			// Operational transactions have some extra reserved space, so that they
167			// are included even if block reached `MAXIMUM_BLOCK_WEIGHT`.
168			weights.reserved = Some(
169				MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT
170			);
171		})
172		.avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO)
173		.build_or_panic();
174
175	pub const SS58Prefix: u8 = 42;
176}
177
178// Configure FRAME pallets to include in runtime.
179
180#[derive_impl(frame_system::config_preludes::SolochainDefaultConfig)]
181impl frame_system::Config for Runtime {
182	/// The block type for the runtime.
183	type Block = Block;
184	/// Block & extrinsics weights: base values and limits.
185	type BlockWeights = RuntimeBlockWeights;
186	/// The maximum length of a block (in bytes).
187	type BlockLength = RuntimeBlockLength;
188	/// The identifier used to distinguish between accounts.
189	type AccountId = AccountId;
190	/// The type for storing how many extrinsics an account has signed.
191	type Nonce = Nonce;
192	/// The type for hashing blocks and tries.
193	type Hash = Hash;
194	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).
195	type BlockHashCount = BlockHashCount;
196	/// The weight of database operations that the runtime can invoke.
197	type DbWeight = RocksDbWeight;
198	/// Version of the runtime.
199	type Version = Version;
200	/// The data to be stored in an account.
201	type AccountData = pallet_balances::AccountData<Balance>;
202	/// This is used as an identifier of the chain. 42 is the generic substrate prefix.
203	type SS58Prefix = SS58Prefix;
204	type MaxConsumers = frame_support::traits::ConstU32<16>;
205}
206
207parameter_types! {
208	pub const UncleGenerations: u32 = 0;
209}
210
211impl pallet_authorship::Config for Runtime {
212	type FindAuthor = ();
213	type EventHandler = ();
214}
215
216parameter_types! {
217	pub const MinimumPeriod: u64 = 5;
218}
219
220impl pallet_timestamp::Config for Runtime {
221	/// A timestamp: milliseconds since the unix epoch.
222	type Moment = u64;
223	type OnTimestampSet = ();
224	type MinimumPeriod = MinimumPeriod;
225	type WeightInfo = ();
226}
227
228parameter_types! {
229	pub const MaxLocks: u32 = 50;
230	pub const MaxReserves: u32 = 50;
231}
232
233impl pallet_balances::Config for Runtime {
234	type MaxLocks = MaxLocks;
235	type MaxReserves = MaxReserves;
236	type ReserveIdentifier = [u8; 8];
237	/// The type for recording an account's balance.
238	type Balance = Balance;
239	/// The ubiquitous event type.
240	type RuntimeEvent = RuntimeEvent;
241	type DustRemoval = ();
242	type ExistentialDeposit = ConstU128<EXISTENTIAL_DEPOSIT>;
243	type AccountStore = System;
244	type WeightInfo = pallet_balances::weights::SubstrateWeight<Runtime>;
245	type FreezeIdentifier = ();
246	type MaxFreezes = ();
247	type RuntimeHoldReason = RuntimeHoldReason;
248	type RuntimeFreezeReason = RuntimeFreezeReason;
249}
250
251impl pallet_transaction_payment::Config for Runtime {
252	type RuntimeEvent = RuntimeEvent;
253	type OnChargeTransaction = FungibleAdapter<Balances, ()>;
254	type OperationalFeeMultiplier = ConstU8<5>;
255	type WeightToFee = IdentityFee<Balance>;
256	type LengthToFee = IdentityFee<Balance>;
257	type FeeMultiplierUpdate = SlowAdjustingFeeUpdate<Self>;
258}
259
260impl pallet_sudo::Config for Runtime {
261	type RuntimeEvent = RuntimeEvent;
262	type RuntimeCall = RuntimeCall;
263	type WeightInfo = pallet_sudo::weights::SubstrateWeight<Runtime>;
264}
265
266impl pallet_utility::Config for Runtime {
267	type RuntimeEvent = RuntimeEvent;
268	type RuntimeCall = RuntimeCall;
269	type PalletsOrigin = OriginCaller;
270	type WeightInfo = pallet_utility::weights::SubstrateWeight<Runtime>;
271}
272
273// Create the runtime by composing the FRAME pallets that were previously configured.
274#[frame_support::runtime]
275mod runtime {
276	#[runtime::runtime]
277	#[runtime::derive(
278		RuntimeCall,
279		RuntimeEvent,
280		RuntimeError,
281		RuntimeOrigin,
282		RuntimeFreezeReason,
283		RuntimeHoldReason,
284		RuntimeSlashReason,
285		RuntimeLockId,
286		RuntimeTask
287	)]
288	pub struct Runtime;
289	#[runtime::pallet_index(0)]
290	pub type System = frame_system;
291	#[runtime::pallet_index(1)]
292	pub type RandomnessCollectiveFlip = pallet_insecure_randomness_collective_flip;
293	#[runtime::pallet_index(2)]
294	pub type Utility = pallet_utility;
295	#[runtime::pallet_index(3)]
296	pub type Timestamp = pallet_timestamp;
297	#[runtime::pallet_index(4)]
298	pub type Balances = pallet_balances;
299	#[runtime::pallet_index(5)]
300	pub type Authorship = pallet_authorship;
301	#[runtime::pallet_index(6)]
302	pub type TransactionPayment = pallet_transaction_payment;
303	#[runtime::pallet_index(7)]
304	pub type Sudo = pallet_sudo;
305	#[runtime::pallet_index(8)]
306	pub type Contracts = pallet_contracts;
307	#[runtime::pallet_index(9)]
308	pub type Revive = pallet_revive;
309	#[runtime::pallet_index(10)]
310	pub type Assets = pallet_assets;
311}
312
313/// The address format for describing accounts.
314pub type Address = sp_runtime::MultiAddress<AccountId, ()>;
315/// Block header type as expected by this runtime.
316pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
317/// Block type as expected by this runtime.
318pub type Block = generic::Block<Header, UncheckedExtrinsic>;
319/// The SignedExtension to the basic transaction logic.
320pub type SignedExtra = (
321	frame_system::CheckNonZeroSender<Runtime>,
322	frame_system::CheckSpecVersion<Runtime>,
323	frame_system::CheckTxVersion<Runtime>,
324	frame_system::CheckGenesis<Runtime>,
325	frame_system::CheckEra<Runtime>,
326	frame_system::CheckNonce<Runtime>,
327	frame_system::CheckWeight<Runtime>,
328	pallet_transaction_payment::ChargeTransactionPayment<Runtime>,
329);
330/// The payload being signed in transactions.
331pub type SignedPayload = generic::SignedPayload<RuntimeCall, SignedExtra>;
332/// Unchecked extrinsic type as expected by this runtime.
333pub type UncheckedExtrinsic =
334	generic::UncheckedExtrinsic<Address, RuntimeCall, Signature, SignedExtra>;
335/// Executive: handles dispatch to the various modules.
336pub type Executive = frame_executive::Executive<
337	Runtime,
338	Block,
339	frame_system::ChainContext<Runtime>,
340	Runtime,
341	AllPalletsWithSystem,
342>;
343
344type EventRecord = frame_system::EventRecord<
345	<Runtime as frame_system::Config>::RuntimeEvent,
346	<Runtime as frame_system::Config>::Hash,
347>;
348
349impl_runtime_apis! {
350	impl sp_api::Core<Block> for Runtime {
351		fn version() -> RuntimeVersion {
352			VERSION
353		}
354
355		fn execute_block(block: Block) {
356			Executive::execute_block(block);
357		}
358
359		fn initialize_block(header: &<Block as BlockT>::Header) -> sp_runtime::ExtrinsicInclusionMode {
360			Executive::initialize_block(header)
361		}
362	}
363
364	impl sp_api::Metadata<Block> for Runtime {
365		fn metadata() -> OpaqueMetadata {
366			OpaqueMetadata::new(Runtime::metadata().into())
367		}
368		fn metadata_at_version(version: u32) -> Option<OpaqueMetadata> {
369			Runtime::metadata_at_version(version)
370		}
371
372		fn metadata_versions() -> Vec<u32> {
373			Runtime::metadata_versions()
374		}
375	}
376
377	impl sp_block_builder::BlockBuilder<Block> for Runtime {
378		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {
379			Executive::apply_extrinsic(extrinsic)
380		}
381
382		fn finalize_block() -> <Block as BlockT>::Header {
383			Executive::finalize_block()
384		}
385
386		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
387			data.create_extrinsics()
388		}
389
390		fn check_inherents(
391			block: Block,
392			data: sp_inherents::InherentData,
393		) -> sp_inherents::CheckInherentsResult {
394			data.check_extrinsics(&block)
395		}
396	}
397
398	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {
399		fn validate_transaction(
400			source: TransactionSource,
401			tx: <Block as BlockT>::Extrinsic,
402			block_hash: <Block as BlockT>::Hash,
403		) -> TransactionValidity {
404			Executive::validate_transaction(source, tx, block_hash)
405		}
406	}
407
408	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {
409		fn offchain_worker(header: &<Block as BlockT>::Header) {
410			Executive::offchain_worker(header)
411		}
412	}
413
414	impl sp_session::SessionKeys<Block> for Runtime {
415		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
416			opaque::SessionKeys::generate(seed)
417		}
418
419		fn decode_session_keys(
420			encoded: Vec<u8>,
421		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {
422			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)
423		}
424	}
425
426	impl frame_system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Nonce> for Runtime {
427		fn account_nonce(account: AccountId) -> Nonce {
428			System::account_nonce(account)
429		}
430	}
431
432	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
433		fn query_info(
434			uxt: <Block as BlockT>::Extrinsic,
435			len: u32,
436		) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
437			TransactionPayment::query_info(uxt, len)
438		}
439		fn query_fee_details(
440			uxt: <Block as BlockT>::Extrinsic,
441			len: u32,
442		) -> pallet_transaction_payment::FeeDetails<Balance> {
443			TransactionPayment::query_fee_details(uxt, len)
444		}
445		fn query_weight_to_fee(weight: Weight) -> Balance {
446			TransactionPayment::weight_to_fee(weight)
447		}
448		fn query_length_to_fee(length: u32) -> Balance {
449			TransactionPayment::length_to_fee(length)
450		}
451	}
452
453	impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi<Block, Balance, RuntimeCall> for Runtime {
454		fn query_call_info(
455			call: RuntimeCall,
456			len: u32,
457		) -> pallet_transaction_payment::RuntimeDispatchInfo<Balance> {
458			TransactionPayment::query_call_info(call, len)
459		}
460		fn query_call_fee_details(
461			call: RuntimeCall,
462			len: u32,
463		) -> pallet_transaction_payment::FeeDetails<Balance> {
464			TransactionPayment::query_call_fee_details(call, len)
465		}
466		fn query_weight_to_fee(weight: Weight) -> Balance {
467			TransactionPayment::weight_to_fee(weight)
468		}
469		fn query_length_to_fee(length: u32) -> Balance {
470			TransactionPayment::length_to_fee(length)
471		}
472	}
473
474	impl pallet_contracts::ContractsApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord>
475		for Runtime
476	{
477		fn call(
478			origin: AccountId,
479			dest: AccountId,
480			value: Balance,
481			gas_limit: Option<Weight>,
482			storage_deposit_limit: Option<Balance>,
483			input_data: Vec<u8>,
484		) -> pallet_contracts::ContractExecResult<Balance, EventRecord> {
485			let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
486			Contracts::bare_call(
487				origin,
488				dest,
489				value,
490				gas_limit,
491				storage_deposit_limit,
492				input_data,
493				CONTRACTS_DEBUG_OUTPUT,
494				CONTRACTS_EVENTS,
495				pallet_contracts::Determinism::Enforced,
496			)
497		}
498
499		fn instantiate(
500			origin: AccountId,
501			value: Balance,
502			gas_limit: Option<Weight>,
503			storage_deposit_limit: Option<Balance>,
504			code: pallet_contracts::Code<Hash>,
505			data: Vec<u8>,
506			salt: Vec<u8>,
507		) -> pallet_contracts::ContractInstantiateResult<AccountId, Balance, EventRecord>
508		{
509			let gas_limit = gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block);
510			Contracts::bare_instantiate(
511				origin,
512				value,
513				gas_limit,
514				storage_deposit_limit,
515				code,
516				data,
517				salt,
518				CONTRACTS_DEBUG_OUTPUT,
519				CONTRACTS_EVENTS,
520			)
521		}
522
523		fn upload_code(
524			origin: AccountId,
525			code: Vec<u8>,
526			storage_deposit_limit: Option<Balance>,
527			determinism: pallet_contracts::Determinism,
528		) -> pallet_contracts::CodeUploadResult<Hash, Balance>
529		{
530			Contracts::bare_upload_code(origin, code, storage_deposit_limit, determinism)
531		}
532
533		fn get_storage(
534			address: AccountId,
535			key: Vec<u8>,
536		) -> pallet_contracts::GetStorageResult {
537			Contracts::get_storage(address, key)
538		}
539	}
540
541	impl pallet_revive::ReviveApi<Block, AccountId, Balance, BlockNumber, Hash, EventRecord> for Runtime
542	{
543		fn call(
544			origin: AccountId,
545			dest: AccountId,
546			value: Balance,
547			gas_limit: Option<Weight>,
548			storage_deposit_limit: Option<Balance>,
549			input_data: Vec<u8>,
550		) -> pallet_revive::ContractExecResult<Balance, EventRecord> {
551			Revive::bare_call(
552				RuntimeOrigin::signed(origin),
553				dest,
554				value,
555				gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block),
556				storage_deposit_limit.unwrap_or(u128::MAX),
557				input_data,
558				REVIVE_DEBUG_OUTPUT,
559				REVIVE_EVENTS,
560			)
561		}
562
563		fn instantiate(
564			origin: AccountId,
565			value: Balance,
566			gas_limit: Option<Weight>,
567			storage_deposit_limit: Option<Balance>,
568			code: pallet_revive::Code<Hash>,
569			data: Vec<u8>,
570			salt: Vec<u8>,
571		) -> pallet_revive::ContractInstantiateResult<AccountId, Balance, EventRecord>
572		{
573			Revive::bare_instantiate(
574				RuntimeOrigin::signed(origin),
575				value,
576				gas_limit.unwrap_or(RuntimeBlockWeights::get().max_block),
577				storage_deposit_limit.unwrap_or(u128::MAX),
578				code,
579				data,
580				salt,
581				REVIVE_DEBUG_OUTPUT,
582				REVIVE_EVENTS,
583			)
584		}
585
586		fn upload_code(
587			origin: AccountId,
588			code: Vec<u8>,
589			storage_deposit_limit: Option<Balance>,
590		) -> pallet_revive::CodeUploadResult<Hash, Balance>
591		{
592			Revive::bare_upload_code(
593				RuntimeOrigin::signed(origin),
594				code,
595				storage_deposit_limit.unwrap_or(u128::MAX),
596			)
597		}
598
599		fn get_storage(
600			address: AccountId,
601			key: Vec<u8>,
602		) -> pallet_revive::GetStorageResult {
603			Revive::get_storage(
604				address,
605				key
606			)
607		}
608	}
609
610	impl sp_genesis_builder::GenesisBuilder<Block> for Runtime {
611		fn build_state(config: Vec<u8>) -> sp_genesis_builder::Result {
612			build_state::<RuntimeGenesisConfig>(config)
613		}
614
615		fn get_preset(id: &Option<sp_genesis_builder::PresetId>) -> Option<Vec<u8>> {
616			get_preset::<RuntimeGenesisConfig>(id, |_| None)
617		}
618
619		fn preset_names() -> Vec<sp_genesis_builder::PresetId> {
620			Default::default()
621		}
622	}
623}