git.delta.rocks / unique-network / refs/commits / 89d693c101e5

difftreelog

NFTPAR-47 + contracts module

str-mv2020-07-02parent: #4ccb943.patch.diff
in: master

9 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2762,8 +2762,10 @@
 version = "2.0.0-rc4"
 dependencies = [
  "futures 0.3.5",
+ "jsonrpc-core",
  "log",
  "nft-runtime",
+ "pallet-contracts-rpc",
  "parking_lot 0.10.2",
  "sc-basic-authorship",
  "sc-cli",
@@ -2773,6 +2775,7 @@
  "sc-executor",
  "sc-finality-grandpa",
  "sc-network",
+ "sc-rpc",
  "sc-service",
  "sc-transaction-pool",
  "sp-consensus",
@@ -2795,6 +2798,9 @@
  "frame-system",
  "pallet-aura",
  "pallet-balances",
+ "pallet-contracts",
+ "pallet-contracts-primitives",
+ "pallet-contracts-rpc-runtime-api",
  "pallet-grandpa",
  "pallet-nft",
  "pallet-randomness-collective-flip",
@@ -3013,6 +3019,67 @@
 ]
 
 [[package]]
+name = "pallet-contracts"
+version = "2.0.0-rc4"
+source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
+dependencies = [
+ "frame-support",
+ "frame-system",
+ "pallet-contracts-primitives",
+ "parity-scale-codec",
+ "parity-wasm",
+ "pwasm-utils",
+ "serde",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-sandbox",
+ "sp-std",
+ "wasmi-validation",
+]
+
+[[package]]
+name = "pallet-contracts-primitives"
+version = "2.0.0-rc4"
+source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
+dependencies = [
+ "parity-scale-codec",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
+name = "pallet-contracts-rpc"
+version = "0.8.0-rc4"
+source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
+dependencies = [
+ "jsonrpc-core",
+ "jsonrpc-core-client",
+ "jsonrpc-derive",
+ "pallet-contracts-primitives",
+ "pallet-contracts-rpc-runtime-api",
+ "parity-scale-codec",
+ "serde",
+ "sp-api",
+ "sp-blockchain",
+ "sp-core",
+ "sp-rpc",
+ "sp-runtime",
+]
+
+[[package]]
+name = "pallet-contracts-rpc-runtime-api"
+version = "0.8.0-rc4"
+source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
+dependencies = [
+ "pallet-contracts-primitives",
+ "parity-scale-codec",
+ "sp-api",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-finality-tracker"
 version = "2.0.0-rc4"
 source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
@@ -3620,6 +3687,17 @@
 checksum = "8e86d370532557ae7573551a1ec8235a0f8d6cb276c7c9e6aa490b511c447485"
 
 [[package]]
+name = "pwasm-utils"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192"
+dependencies = [
+ "byteorder",
+ "log",
+ "parity-wasm",
+]
+
+[[package]]
 name = "quick-error"
 version = "1.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -5576,6 +5654,19 @@
 ]
 
 [[package]]
+name = "sp-sandbox"
+version = "0.8.0-rc4"
+source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
+dependencies = [
+ "parity-scale-codec",
+ "sp-core",
+ "sp-io",
+ "sp-std",
+ "sp-wasm-interface",
+ "wasmi",
+]
+
+[[package]]
 name = "sp-serializer"
 version = "2.0.0-rc4"
 source = "git+https://github.com/paritytech/substrate.git?tag=v2.0.0-rc4#00768a1f21a579c478fe5d4f51e1fa71f7db9fd4"
modifiednode/Cargo.tomldiffbeforeafterboth
--- a/node/Cargo.toml
+++ b/node/Cargo.toml
@@ -20,6 +20,16 @@
 log = '0.4.8'
 parking_lot = '0.10.0'
 structopt = '0.3.8'
+jsonrpc-core = '14.0.5'
+
+[dependencies.pallet-contracts-rpc]
+git = 'https://github.com/paritytech/substrate.git'
+version = '0.8.0-rc4'
+tag = 'v2.0.0-rc4'
+
+[dependencies.sc-rpc]
+git = 'https://github.com/paritytech/substrate.git'
+tag = 'v2.0.0-rc4'
 
 [dependencies.nft-runtime]
 path = '../runtime'
modifiednode/src/chain_spec.rsdiffbeforeafterboth
--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -8,6 +8,8 @@
 use sp_runtime::traits::{Verify, IdentifyAccount};
 use sc_service::ChainType;
 
+use nft_runtime::{ContractsConfig, ContractsSchedule};
+
 // Note this is the URL for the telemetry server
 //const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
 
@@ -111,6 +113,12 @@
 		balances: Some(BalancesConfig {
 			balances: endowed_accounts.iter().cloned().map(|k|(k, 1 << 60)).collect(),
 		}),
+		contracts: Some(ContractsConfig {
+            current_schedule: ContractsSchedule {
+              //      enable_println,
+                    ..Default::default()
+            },
+        }),
 		aura: Some(AuraConfig {
 			authorities: initial_authorities.iter().map(|x| (x.0.clone())).collect(),
 		}),
modifiednode/src/service.rsdiffbeforeafterboth
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -27,6 +27,7 @@
 /// be able to perform chain operations.
 macro_rules! new_full_start {
 	($config:expr) => {{
+		use jsonrpc_core::IoHandler;
 		use std::sync::Arc;
 		use sp_consensus_aura::sr25519::AuthorityPair as AuraPair;
 
@@ -86,7 +87,15 @@
 				import_setup = Some((grandpa_block_import, grandpa_link));
 
 				Ok(import_queue)
-			})?;
+			})?
+			.with_rpc_extensions(|builder| -> Result<IoHandler<sc_rpc::Metadata>, _> {
+                let handler = pallet_contracts_rpc::Contracts::new(builder.client().clone());
+                let delegate = pallet_contracts_rpc::ContractsApi::to_delegate(handler);
+
+                let mut io = IoHandler::default();
+                io.extend_with(delegate);
+                Ok(io)
+            })?;
 
 		(builder, import_setup, inherent_data_providers)
 	}}
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -58,10 +58,7 @@
 
         /// Next available collection ID
         pub NextCollectionID get(fn next_collection_id): u64;
-
         pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
-        //pub Collection get(collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
-
         pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
 
         /// Balance owner per collection map
@@ -69,10 +66,10 @@
         pub ApprovedList get(fn approved): map hasher(blake2_128_concat) (u64, u64) => Vec<T::AccountId>;
 
         pub ItemList get(fn item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
-        // pub ItemList get(item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
+        pub ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;
+
+        pub AddressTokens get(fn address_tokens): map hasher(blake2_128_concat) (u64, T::AccountId) => Vec<u64>;
 
-        pub ItemListIndex get(fn item_index): map hasher(blake2_128_concat) u64 => u64;
-        // pub ItemListIndex get(item_index): map hasher(blake2_128_concat) u64 => u64;
     }
 }
 
@@ -247,7 +244,11 @@
                 data: properties,
             };
 
+
             let current_index = <ItemListIndex>::get(collection_id);
+
+            Self::add_token_index(collection_id, current_index, new_item.owner.clone())?;
+
             <ItemListIndex>::insert(collection_id, current_index);
             <ItemList<T>>::insert((collection_id, current_index), new_item);
 
@@ -279,6 +280,8 @@
             }
             <ItemList<T>>::remove((collection_id, item_id));
 
+            Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
+
             // update balance
             let new_balance = <Balance<T>>::get((collection_id, item.owner.clone())) - 1;
             <Balance<T>>::insert((collection_id, item.owner.clone()), new_balance);
@@ -319,9 +322,13 @@
             <Balance<T>>::insert((collection_id, new_owner.clone()), balance_new_owner);
 
             // change owner
-            item.owner = new_owner;
+            let old_owner = item.owner.clone();
+            item.owner = new_owner.clone();
             <ItemList<T>>::insert((collection_id, item_id), item);
 
+            // update index collection
+            Self::move_token_index(collection_id, item_id, old_owner, new_owner.clone())?;
+
             // reset approved list
             let itm: Vec<T::AccountId> = Vec::new();
             <ApprovedList<T>>::insert((collection_id, item_id), itm);
@@ -401,3 +408,55 @@
         }
     }
 }
+
+
+impl<T: Trait> Module<T> {
+    fn add_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
+        
+        let list_exists = <AddressTokens<T>>::contains_key((collection_id, owner.clone()));
+        if list_exists {
+
+            let mut list = <AddressTokens<T>>::get((collection_id, owner.clone()));
+            let item_contains = list.contains(&item_index.clone());
+
+            if !item_contains {
+                list.push(item_index.clone());
+            }
+
+            <AddressTokens<T>>::insert((collection_id, owner.clone()), list);
+
+        } else {
+
+            let mut itm = Vec::new();
+            itm.push(item_index.clone());
+            <AddressTokens<T>>::insert((collection_id, owner), itm);
+        }
+
+        Ok(())
+    }
+
+    fn remove_token_index(collection_id: u64, item_index: u64, owner: T::AccountId) -> DispatchResult {
+        
+        let list_exists = <AddressTokens<T>>::contains_key((collection_id, owner.clone()));
+        if list_exists {
+
+            let mut list = <AddressTokens<T>>::get((collection_id, owner.clone()));
+            let item_contains = list.contains(&item_index.clone());
+
+            if item_contains {
+                list.retain(|&item| item != item_index);
+                <AddressTokens<T>>::insert((collection_id, owner), list);
+            }
+        }
+
+        Ok(())
+    }
+
+    fn move_token_index(collection_id: u64, item_index: u64, old_owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
+        
+        Self::remove_token_index(collection_id, item_index, old_owner)?;
+        Self::add_token_index(collection_id, item_index, new_owner)?;
+        
+        Ok(())
+    }
+}
\ No newline at end of file
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -1,7 +1,12 @@
 // Creating mock runtime here
 
 use crate::{Module, Trait};
-use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
+use frame_support::{
+    impl_outer_origin, parameter_types, 
+    weights::{ 
+        Weight,
+        constants::{ BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND },
+    }};
 use frame_system as system;
 use sp_core::H256;
 use sp_runtime::{
@@ -11,7 +16,8 @@
 };
 
 impl_outer_origin! {
-    pub enum Origin for Test {}
+    pub enum Origin for Test {
+    }
 }
 
 // For testing the pallet, we construct most of a mock runtime. This means
@@ -24,12 +30,17 @@
     pub const MaximumBlockWeight: Weight = 1024;
     pub const MaximumBlockLength: u32 = 2 * 1024;
     pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
+    pub MaximumExtrinsicWeight: Weight = 10 * WEIGHT_PER_SECOND;
 }
+
 impl system::Trait for Test {
     type Origin = Origin;
     type Call = ();
     type Index = u64;
     type BlockNumber = u64;
+    type BaseCallFilter = ();
+    type DbWeight = RocksDbWeight;
+    type BlockExecutionWeight = BlockExecutionWeight;
     type Hash = H256;
     type Hashing = BlakeTwo256;
     type AccountId = u64;
@@ -37,6 +48,8 @@
     type Header = Header;
     type Event = ();
     type BlockHashCount = BlockHashCount;
+    type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
+    type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
     type MaximumBlockWeight = MaximumBlockWeight;
     type MaximumBlockLength = MaximumBlockLength;
     type AvailableBlockRatio = AvailableBlockRatio;
@@ -49,6 +62,7 @@
 impl Trait for Test {
     type Event = ();
 }
+
 pub type TemplateModule = Module<Test>;
 
 // This function basically just builds a genesis storage key/value store according to
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -297,3 +297,50 @@
         assert_ok!(TemplateModule::transfer_from(origin1.clone(), 1, 1, 2));
     });
 }
+
+#[test]
+fn index_list() {
+    new_test_ext().execute_with(|| {
+        let size = 1024;
+        let origin1 = Origin::signed(1);
+        let origin2 = Origin::signed(2);
+        let origin3 = Origin::signed(3);
+
+        assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+        assert_ok!(TemplateModule::create_collection(origin2.clone(), size));
+        assert_ok!(TemplateModule::create_collection(origin3.clone(), size));
+
+        assert_eq!(TemplateModule::collection(1).owner, 1);
+        assert_eq!(TemplateModule::collection(2).owner, 2);
+        assert_eq!(TemplateModule::collection(3).owner, 3);
+
+        // create items
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 1, 1].to_vec()
+        ));
+
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 1, 2].to_vec()
+        ));
+
+        assert_ok!(TemplateModule::create_item(
+            origin1.clone(),
+            1,
+            [1, 2, 3].to_vec()
+        ));
+
+        assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 3);
+
+        // burn one
+        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 2));
+        assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 2);
+
+        // burn another one
+        assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 3));
+        assert_eq!(TemplateModule::address_tokens((1, 1))[0], 1);
+    });
+}
\ No newline at end of file
modifiedruntime/Cargo.tomldiffbeforeafterboth
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -4,6 +4,9 @@
     'aura/std',
     'balances/std',
     'codec/std',
+    'contracts/std',
+    'contracts-primitives/std',
+    'contracts-rpc-runtime-api/std',
     'frame-executive/std',
     'frame-support/std',
     'grandpa/std',
@@ -47,6 +50,27 @@
 package = 'parity-scale-codec'
 version = '1.3.1'
 
+[dependencies.contracts]
+git = 'https://github.com/paritytech/substrate.git'
+default-features = false
+package = 'pallet-contracts'
+tag = 'v2.0.0-rc4'
+version = '2.0.0-rc4'
+
+[dependencies.contracts-primitives]
+git = 'https://github.com/paritytech/substrate.git'
+default-features = false
+package = 'pallet-contracts-primitives'
+tag = 'v2.0.0-rc4'
+version = '2.0.0-rc4'
+
+[dependencies.contracts-rpc-runtime-api]
+git = 'https://github.com/paritytech/substrate.git'
+default-features = false
+package = 'pallet-contracts-rpc-runtime-api'
+version = '0.8.0-rc4'
+tag = 'v2.0.0-rc4'
+
 [dependencies.frame-executive]
 default-features = false
 git = 'https://github.com/paritytech/substrate.git'
modifiedruntime/src/lib.rsdiffbeforeafterboth
before · runtime/src/lib.rs
1//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.23#![cfg_attr(not(feature = "std"), no_std)]4// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.5#![recursion_limit="256"]67// Make the WASM binary available.8#[cfg(feature = "std")]9include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1011use sp_std::prelude::*;12use sp_core::{crypto::KeyTypeId, OpaqueMetadata};13use sp_runtime::{14	ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature,15	transaction_validity::{TransactionValidity, TransactionSource},16};17use sp_runtime::traits::{18	BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating,19};20use sp_api::impl_runtime_apis;21use sp_consensus_aura::sr25519::AuthorityId as AuraId;22use grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};23use grandpa::fg_primitives;24use sp_version::RuntimeVersion;25#[cfg(feature = "std")]26use sp_version::NativeVersion;2728// A few exports that help ease life for downstream crates.29#[cfg(any(feature = "std", test))]30pub use sp_runtime::BuildStorage;31pub use timestamp::Call as TimestampCall;32pub use balances::Call as BalancesCall;33pub use sp_runtime::{Permill, Perbill};34pub use frame_support::{35	construct_runtime, parameter_types, StorageValue,36	traits::{KeyOwnerProofSystem, Randomness},37	weights::{38		Weight, IdentityFee,39		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},40	},41};4243/// Importing a template pallet44pub use nft;4546/// An index to a block.47pub type BlockNumber = u32;4849/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.50pub type Signature = MultiSignature;5152/// Some way of identifying an account on the chain. We intentionally make it equivalent53/// to the public key of our transaction signing scheme.54pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;5556/// The type for looking up accounts. We don't expect more than 4 billion of them, but you57/// never know...58pub type AccountIndex = u32;5960/// Balance of an account.61pub type Balance = u128;6263/// Index of a transaction in the chain.64pub type Index = u32;6566/// A hash of some data used by the chain.67pub type Hash = sp_core::H256;6869/// Digest item type.70pub type DigestItem = generic::DigestItem<Hash>;7172/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know73/// the specifics of the runtime. They can then be made to be agnostic over specific formats74/// of data like extrinsics, allowing for them to continue syncing the network through upgrades75/// to even the core data structures.76pub mod opaque {77	use super::*;7879	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;8081	/// Opaque block header type.82	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;83	/// Opaque block type.84	pub type Block = generic::Block<Header, UncheckedExtrinsic>;85	/// Opaque block identifier type.86	pub type BlockId = generic::BlockId<Block>;8788	impl_opaque_keys! {89		pub struct SessionKeys {90			pub aura: Aura,91			pub grandpa: Grandpa,92		}93	}94}9596/// This runtime version.97pub const VERSION: RuntimeVersion = RuntimeVersion {98    spec_name: create_runtime_str!("nft"),99    impl_name: create_runtime_str!("nft"),100	authoring_version: 1,101	spec_version: 1,102	impl_version: 1,103	apis: RUNTIME_API_VERSIONS,104	transaction_version: 1,105};106107pub const MILLISECS_PER_BLOCK: u64 = 6000;108109pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;110111// These time units are defined in number of blocks.112pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);113pub const HOURS: BlockNumber = MINUTES * 60;114pub const DAYS: BlockNumber = HOURS * 24;115116/// The version information used to identify this runtime when compiled natively.117#[cfg(feature = "std")]118pub fn native_version() -> NativeVersion {119	NativeVersion {120		runtime_version: VERSION,121		can_author_with: Default::default(),122	}123}124125parameter_types! {126	pub const BlockHashCount: BlockNumber = 2400;127	/// We allow for 2 seconds of compute with a 6 second average block time.128	pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;129	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);130	/// Assume 10% of weight for average on_initialize calls.131	pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()132		.saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();133	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;134	pub const Version: RuntimeVersion = VERSION;135}136137impl system::Trait for Runtime {138	/// The basic call filter to use in dispatchable.139	type BaseCallFilter = ();140	/// The identifier used to distinguish between accounts.141	type AccountId = AccountId;142	/// The aggregated dispatch type that is available for extrinsics.143	type Call = Call;144	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.145	type Lookup = IdentityLookup<AccountId>;146	/// The index type for storing how many extrinsics an account has signed.147	type Index = Index;148	/// The index type for blocks.149	type BlockNumber = BlockNumber;150	/// The type for hashing blocks and tries.151	type Hash = Hash;152	/// The hashing algorithm used.153	type Hashing = BlakeTwo256;154	/// The header type.155	type Header = generic::Header<BlockNumber, BlakeTwo256>;156	/// The ubiquitous event type.157	type Event = Event;158	/// The ubiquitous origin type.159	type Origin = Origin;160	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).161	type BlockHashCount = BlockHashCount;162	/// Maximum weight of each block.163	type MaximumBlockWeight = MaximumBlockWeight;164	/// The weight of database operations that the runtime can invoke.165	type DbWeight = RocksDbWeight;166	/// The weight of the overhead invoked on the block import process, independent of the167	/// extrinsics included in that block.168	type BlockExecutionWeight = BlockExecutionWeight;169	/// The base weight of any extrinsic processed by the runtime, independent of the170	/// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)171	type ExtrinsicBaseWeight = ExtrinsicBaseWeight;172	/// The maximum weight that a single extrinsic of `Normal` dispatch class can have,173	/// idependent of the logic of that extrinsics. (Roughly max block weight - average on174	/// initialize cost).175	type MaximumExtrinsicWeight = MaximumExtrinsicWeight;176	/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.177	type MaximumBlockLength = MaximumBlockLength;178	/// Portion of the block weight that is available to all normal transactions.179	type AvailableBlockRatio = AvailableBlockRatio;180	/// Version of the runtime.181	type Version = Version;182	/// Converts a module to the index of the module in `construct_runtime!`.183	///184	/// This type is being generated by `construct_runtime!`.185	type ModuleToIndex = ModuleToIndex;186	/// What to do if a new account is created.187	type OnNewAccount = ();188	/// What to do if an account is fully reaped from the system.189	type OnKilledAccount = ();190	/// The data to be stored in an account.191	type AccountData = balances::AccountData<Balance>;192}193194impl aura::Trait for Runtime {195	type AuthorityId = AuraId;196}197198impl grandpa::Trait for Runtime {199	type Event = Event;200	type Call = Call;201202	type KeyOwnerProofSystem = ();203204	type KeyOwnerProof =205		<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;206207	type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(208		KeyTypeId,209		GrandpaId,210	)>>::IdentificationTuple;211212	type HandleEquivocation = ();213}214215parameter_types! {216	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;217}218219impl timestamp::Trait for Runtime {220	/// A timestamp: milliseconds since the unix epoch.221	type Moment = u64;222	type OnTimestampSet = Aura;223	type MinimumPeriod = MinimumPeriod;224}225226parameter_types! {227	pub const ExistentialDeposit: u128 = 500;228}229230impl balances::Trait for Runtime {231	/// The type for recording an account's balance.232	type Balance = Balance;233	/// The ubiquitous event type.234	type Event = Event;235	type DustRemoval = ();236	type ExistentialDeposit = ExistentialDeposit;237	type AccountStore = System;238}239240parameter_types! {241	pub const TransactionByteFee: Balance = 1;242}243244impl transaction_payment::Trait for Runtime {245	type Currency = balances::Module<Runtime>;246	type OnTransactionPayment = ();247	type TransactionByteFee = TransactionByteFee;248	type WeightToFee = IdentityFee<Balance>;249	type FeeMultiplierUpdate = ();250}251252impl sudo::Trait for Runtime {253	type Event = Event;254	type Call = Call;255}256257/// Used for the module template in `./template.rs`258impl nft::Trait for Runtime {259    type Event = Event;260}261262construct_runtime!(263	pub enum Runtime where264		Block = Block,265		NodeBlock = opaque::Block,266		UncheckedExtrinsic = UncheckedExtrinsic267	{268		System: system::{Module, Call, Config, Storage, Event<T>},269		RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},270		Timestamp: timestamp::{Module, Call, Storage, Inherent},271		Aura: aura::{Module, Config<T>, Inherent(Timestamp)},272		Grandpa: grandpa::{Module, Call, Storage, Config, Event},273		Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},274		TransactionPayment: transaction_payment::{Module, Storage},275		Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},276		// Used for the module template in `./template.rs`277        Nft: nft::{Module, Call, Storage, Event<T>},278	}279);280281/// The address format for describing accounts.282pub type Address = AccountId;283/// Block header type as expected by this runtime.284pub type Header = generic::Header<BlockNumber, BlakeTwo256>;285/// Block type as expected by this runtime.286pub type Block = generic::Block<Header, UncheckedExtrinsic>;287/// A Block signed with a Justification288pub type SignedBlock = generic::SignedBlock<Block>;289/// BlockId type as expected by this runtime.290pub type BlockId = generic::BlockId<Block>;291/// The SignedExtension to the basic transaction logic.292pub type SignedExtra = (293	system::CheckSpecVersion<Runtime>,294	system::CheckTxVersion<Runtime>,295	system::CheckGenesis<Runtime>,296	system::CheckEra<Runtime>,297	system::CheckNonce<Runtime>,298	system::CheckWeight<Runtime>,299	transaction_payment::ChargeTransactionPayment<Runtime>300);301/// Unchecked extrinsic type as expected by this runtime.302pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;303/// Extrinsic type that has already been checked.304pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;305/// Executive: handles dispatch to the various modules.306pub type Executive = frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;307308impl_runtime_apis! {309	impl sp_api::Core<Block> for Runtime {310		fn version() -> RuntimeVersion {311			VERSION312		}313314		fn execute_block(block: Block) {315			Executive::execute_block(block)316		}317318		fn initialize_block(header: &<Block as BlockT>::Header) {319			Executive::initialize_block(header)320		}321	}322323	impl sp_api::Metadata<Block> for Runtime {324		fn metadata() -> OpaqueMetadata {325			Runtime::metadata().into()326		}327	}328329	impl sp_block_builder::BlockBuilder<Block> for Runtime {330		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {331			Executive::apply_extrinsic(extrinsic)332		}333334		fn finalize_block() -> <Block as BlockT>::Header {335			Executive::finalize_block()336		}337338		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {339			data.create_extrinsics()340		}341342		fn check_inherents(343			block: Block,344			data: sp_inherents::InherentData,345		) -> sp_inherents::CheckInherentsResult {346			data.check_extrinsics(&block)347		}348349		fn random_seed() -> <Block as BlockT>::Hash {350			RandomnessCollectiveFlip::random_seed()351		}352	}353354	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {355		fn validate_transaction(356			source: TransactionSource,357			tx: <Block as BlockT>::Extrinsic,358		) -> TransactionValidity {359			Executive::validate_transaction(source, tx)360		}361	}362363	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {364		fn offchain_worker(header: &<Block as BlockT>::Header) {365			Executive::offchain_worker(header)366		}367	}368369	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {370		fn slot_duration() -> u64 {371			Aura::slot_duration()372		}373374		fn authorities() -> Vec<AuraId> {375			Aura::authorities()376		}377	}378379	impl sp_session::SessionKeys<Block> for Runtime {380		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {381			opaque::SessionKeys::generate(seed)382		}383384		fn decode_session_keys(385			encoded: Vec<u8>,386		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {387			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)388		}389	}390391	impl fg_primitives::GrandpaApi<Block> for Runtime {392		fn grandpa_authorities() -> GrandpaAuthorityList {393			Grandpa::grandpa_authorities()394		}395396		fn submit_report_equivocation_extrinsic(397			_equivocation_proof: fg_primitives::EquivocationProof<398				<Block as BlockT>::Hash,399				NumberFor<Block>,400			>,401			_key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,402		) -> Option<()> {403			None404		}405406		fn generate_key_ownership_proof(407			_set_id: fg_primitives::SetId,408			_authority_id: GrandpaId,409		) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {410			// NOTE: this is the only implementation possible since we've411			// defined our key owner proof type as a bottom type (i.e. a type412			// with no values).413			None414		}415	}416}
after · runtime/src/lib.rs
1//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.23#![cfg_attr(not(feature = "std"), no_std)]4// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.5#![recursion_limit="256"]67// Make the WASM binary available.8#[cfg(feature = "std")]9include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1011use sp_std::prelude::*;12use sp_core::{crypto::KeyTypeId, OpaqueMetadata};13use sp_runtime::{14	ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature,15	transaction_validity::{TransactionValidity, TransactionSource},16};17use sp_runtime::traits::{18	BlakeTwo256, Block as BlockT, IdentityLookup, Verify, IdentifyAccount, NumberFor, Saturating,19};20use sp_api::impl_runtime_apis;21use sp_consensus_aura::sr25519::AuthorityId as AuraId;22use grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};23use grandpa::fg_primitives;24use sp_version::RuntimeVersion;25#[cfg(feature = "std")]26use sp_version::NativeVersion;27use contracts_rpc_runtime_api::ContractExecResult;2829// A few exports that help ease life for downstream crates.30#[cfg(any(feature = "std", test))]31pub use sp_runtime::BuildStorage;32pub use timestamp::Call as TimestampCall;33pub use balances::Call as BalancesCall;34pub use sp_runtime::{Permill, Perbill};35pub use contracts::Schedule as ContractsSchedule;36pub use frame_support::{37	construct_runtime, parameter_types, StorageValue,38	traits::{KeyOwnerProofSystem, Randomness},39	weights::{40		Weight, IdentityFee,41		constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},42	},43};4445/// Importing a template pallet46pub use nft;4748/// An index to a block.49pub type BlockNumber = u32;5051/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.52pub type Signature = MultiSignature;5354/// Some way of identifying an account on the chain. We intentionally make it equivalent55/// to the public key of our transaction signing scheme.56pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;5758/// The type for looking up accounts. We don't expect more than 4 billion of them, but you59/// never know...60pub type AccountIndex = u32;6162/// Balance of an account.63pub type Balance = u128;6465/// Index of a transaction in the chain.66pub type Index = u32;6768/// A hash of some data used by the chain.69pub type Hash = sp_core::H256;7071/// Digest item type.72pub type DigestItem = generic::DigestItem<Hash>;7374pub const MILLICENTS: Balance = 1_000_000_000;75pub const CENTS: Balance = 1_000 * MILLICENTS;76pub const DOLLARS: Balance = 100 * CENTS;7778/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know79/// the specifics of the runtime. They can then be made to be agnostic over specific formats80/// of data like extrinsics, allowing for them to continue syncing the network through upgrades81/// to even the core data structures.82pub mod opaque {83	use super::*;8485	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;8687	/// Opaque block header type.88	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;89	/// Opaque block type.90	pub type Block = generic::Block<Header, UncheckedExtrinsic>;91	/// Opaque block identifier type.92	pub type BlockId = generic::BlockId<Block>;9394	impl_opaque_keys! {95		pub struct SessionKeys {96			pub aura: Aura,97			pub grandpa: Grandpa,98		}99	}100}101102/// This runtime version.103pub const VERSION: RuntimeVersion = RuntimeVersion {104    spec_name: create_runtime_str!("nft"),105    impl_name: create_runtime_str!("nft"),106	authoring_version: 1,107	spec_version: 1,108	impl_version: 1,109	apis: RUNTIME_API_VERSIONS,110	transaction_version: 1,111};112113pub const MILLISECS_PER_BLOCK: u64 = 6000;114115pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;116117// These time units are defined in number of blocks.118pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);119pub const HOURS: BlockNumber = MINUTES * 60;120pub const DAYS: BlockNumber = HOURS * 24;121122/// The version information used to identify this runtime when compiled natively.123#[cfg(feature = "std")]124pub fn native_version() -> NativeVersion {125	NativeVersion {126		runtime_version: VERSION,127		can_author_with: Default::default(),128	}129}130131parameter_types! {132	pub const BlockHashCount: BlockNumber = 2400;133	/// We allow for 2 seconds of compute with a 6 second average block time.134	pub const MaximumBlockWeight: Weight = 2 * WEIGHT_PER_SECOND;135	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);136	/// Assume 10% of weight for average on_initialize calls.137	pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get()138		.saturating_sub(Perbill::from_percent(10)) * MaximumBlockWeight::get();139	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;140	pub const Version: RuntimeVersion = VERSION;141}142143impl system::Trait for Runtime {144	/// The basic call filter to use in dispatchable.145	type BaseCallFilter = ();146	/// The identifier used to distinguish between accounts.147	type AccountId = AccountId;148	/// The aggregated dispatch type that is available for extrinsics.149	type Call = Call;150	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.151	type Lookup = IdentityLookup<AccountId>;152	/// The index type for storing how many extrinsics an account has signed.153	type Index = Index;154	/// The index type for blocks.155	type BlockNumber = BlockNumber;156	/// The type for hashing blocks and tries.157	type Hash = Hash;158	/// The hashing algorithm used.159	type Hashing = BlakeTwo256;160	/// The header type.161	type Header = generic::Header<BlockNumber, BlakeTwo256>;162	/// The ubiquitous event type.163	type Event = Event;164	/// The ubiquitous origin type.165	type Origin = Origin;166	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).167	type BlockHashCount = BlockHashCount;168	/// Maximum weight of each block.169	type MaximumBlockWeight = MaximumBlockWeight;170	/// The weight of database operations that the runtime can invoke.171	type DbWeight = RocksDbWeight;172	/// The weight of the overhead invoked on the block import process, independent of the173	/// extrinsics included in that block.174	type BlockExecutionWeight = BlockExecutionWeight;175	/// The base weight of any extrinsic processed by the runtime, independent of the176	/// logic of that extrinsic. (Signature verification, nonce increment, fee, etc...)177	type ExtrinsicBaseWeight = ExtrinsicBaseWeight;178	/// The maximum weight that a single extrinsic of `Normal` dispatch class can have,179	/// idependent of the logic of that extrinsics. (Roughly max block weight - average on180	/// initialize cost).181	type MaximumExtrinsicWeight = MaximumExtrinsicWeight;182	/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.183	type MaximumBlockLength = MaximumBlockLength;184	/// Portion of the block weight that is available to all normal transactions.185	type AvailableBlockRatio = AvailableBlockRatio;186	/// Version of the runtime.187	type Version = Version;188	/// Converts a module to the index of the module in `construct_runtime!`.189	///190	/// This type is being generated by `construct_runtime!`.191	type ModuleToIndex = ModuleToIndex;192	/// What to do if a new account is created.193	type OnNewAccount = ();194	/// What to do if an account is fully reaped from the system.195	type OnKilledAccount = ();196	/// The data to be stored in an account.197	type AccountData = balances::AccountData<Balance>;198}199200impl aura::Trait for Runtime {201	type AuthorityId = AuraId;202}203204impl grandpa::Trait for Runtime {205	type Event = Event;206	type Call = Call;207208	type KeyOwnerProofSystem = ();209210	type KeyOwnerProof =211		<Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, GrandpaId)>>::Proof;212213	type KeyOwnerIdentification = <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(214		KeyTypeId,215		GrandpaId,216	)>>::IdentificationTuple;217218	type HandleEquivocation = ();219}220221parameter_types! {222	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;223}224225impl timestamp::Trait for Runtime {226	/// A timestamp: milliseconds since the unix epoch.227	type Moment = u64;228	type OnTimestampSet = Aura;229	type MinimumPeriod = MinimumPeriod;230}231232parameter_types! {233	pub const ExistentialDeposit: u128 = 500;234}235236impl balances::Trait for Runtime {237	/// The type for recording an account's balance.238	type Balance = Balance;239	/// The ubiquitous event type.240	type Event = Event;241	type DustRemoval = ();242	type ExistentialDeposit = ExistentialDeposit;243	type AccountStore = System;244}245246parameter_types! {247	pub const TransactionByteFee: Balance = 1;248}249250impl transaction_payment::Trait for Runtime {251	type Currency = balances::Module<Runtime>;252	type OnTransactionPayment = ();253	type TransactionByteFee = TransactionByteFee;254	type WeightToFee = IdentityFee<Balance>;255	type FeeMultiplierUpdate = ();256}257258impl sudo::Trait for Runtime {259	type Event = Event;260	type Call = Call;261}262263parameter_types! {264    pub const TombstoneDeposit: Balance = 16 * MILLICENTS;265    pub const RentByteFee: Balance = 4 * MILLICENTS;266    pub const RentDepositOffset: Balance = 1000 * MILLICENTS;267    pub const SurchargeReward: Balance = 150 * MILLICENTS;268}269270impl contracts::Trait for Runtime {271    type Time = Timestamp;272    type Randomness = RandomnessCollectiveFlip;273    type Currency = Balances;274    type Event = Event;275    type DetermineContractAddress = contracts::SimpleAddressDeterminer<Runtime>;276    type TrieIdGenerator = contracts::TrieIdFromParentCounter<Runtime>;277    type RentPayment = ();278    type SignedClaimHandicap = contracts::DefaultSignedClaimHandicap;279    type TombstoneDeposit = TombstoneDeposit;280    type StorageSizeOffset = contracts::DefaultStorageSizeOffset;281    type RentByteFee = RentByteFee;282    type RentDepositOffset = RentDepositOffset;283    type SurchargeReward = SurchargeReward;284    type MaxDepth = contracts::DefaultMaxDepth;285    type MaxValueSize = contracts::DefaultMaxValueSize;286    type WeightPrice = transaction_payment::Module<Self>;287}288289/// Used for the module template in `./template.rs`290impl nft::Trait for Runtime {291    type Event = Event;292}293294construct_runtime!(295	pub enum Runtime where296		Block = Block,297		NodeBlock = opaque::Block,298		UncheckedExtrinsic = UncheckedExtrinsic299	{300		System: system::{Module, Call, Config, Storage, Event<T>},301		RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},302		Contracts: contracts::{Module, Call, Config, Storage, Event<T>},303		Timestamp: timestamp::{Module, Call, Storage, Inherent},304		Aura: aura::{Module, Config<T>, Inherent(Timestamp)},305		Grandpa: grandpa::{Module, Call, Storage, Config, Event},306		Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},307		TransactionPayment: transaction_payment::{Module, Storage},308		Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},309		// Used for the module template in `./template.rs`310        Nft: nft::{Module, Call, Storage, Event<T>},311	}312);313314/// The address format for describing accounts.315pub type Address = AccountId;316/// Block header type as expected by this runtime.317pub type Header = generic::Header<BlockNumber, BlakeTwo256>;318/// Block type as expected by this runtime.319pub type Block = generic::Block<Header, UncheckedExtrinsic>;320/// A Block signed with a Justification321pub type SignedBlock = generic::SignedBlock<Block>;322/// BlockId type as expected by this runtime.323pub type BlockId = generic::BlockId<Block>;324/// The SignedExtension to the basic transaction logic.325pub type SignedExtra = (326	system::CheckSpecVersion<Runtime>,327	system::CheckTxVersion<Runtime>,328	system::CheckGenesis<Runtime>,329	system::CheckEra<Runtime>,330	system::CheckNonce<Runtime>,331	system::CheckWeight<Runtime>,332	transaction_payment::ChargeTransactionPayment<Runtime>333);334/// Unchecked extrinsic type as expected by this runtime.335pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;336/// Extrinsic type that has already been checked.337pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;338/// Executive: handles dispatch to the various modules.339pub type Executive = frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;340341impl_runtime_apis! {342	impl sp_api::Core<Block> for Runtime {343		fn version() -> RuntimeVersion {344			VERSION345		}346347		fn execute_block(block: Block) {348			Executive::execute_block(block)349		}350351		fn initialize_block(header: &<Block as BlockT>::Header) {352			Executive::initialize_block(header)353		}354	}355356	impl sp_api::Metadata<Block> for Runtime {357		fn metadata() -> OpaqueMetadata {358			Runtime::metadata().into()359		}360	}361362	impl sp_block_builder::BlockBuilder<Block> for Runtime {363		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {364			Executive::apply_extrinsic(extrinsic)365		}366367		fn finalize_block() -> <Block as BlockT>::Header {368			Executive::finalize_block()369		}370371		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {372			data.create_extrinsics()373		}374375		fn check_inherents(376			block: Block,377			data: sp_inherents::InherentData,378		) -> sp_inherents::CheckInherentsResult {379			data.check_extrinsics(&block)380		}381382		fn random_seed() -> <Block as BlockT>::Hash {383			RandomnessCollectiveFlip::random_seed()384		}385	}386387	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {388		fn validate_transaction(389			source: TransactionSource,390			tx: <Block as BlockT>::Extrinsic,391		) -> TransactionValidity {392			Executive::validate_transaction(source, tx)393		}394	}395396	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {397		fn offchain_worker(header: &<Block as BlockT>::Header) {398			Executive::offchain_worker(header)399		}400	}401402	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {403		fn slot_duration() -> u64 {404			Aura::slot_duration()405		}406407		fn authorities() -> Vec<AuraId> {408			Aura::authorities()409		}410	}411412	impl sp_session::SessionKeys<Block> for Runtime {413		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {414			opaque::SessionKeys::generate(seed)415		}416417		fn decode_session_keys(418			encoded: Vec<u8>,419		) -> Option<Vec<(Vec<u8>, KeyTypeId)>> {420			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)421		}422	}423424	impl fg_primitives::GrandpaApi<Block> for Runtime {425		fn grandpa_authorities() -> GrandpaAuthorityList {426			Grandpa::grandpa_authorities()427		}428429		fn submit_report_equivocation_extrinsic(430			_equivocation_proof: fg_primitives::EquivocationProof<431				<Block as BlockT>::Hash,432				NumberFor<Block>,433			>,434			_key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof,435		) -> Option<()> {436			None437		}438439		fn generate_key_ownership_proof(440			_set_id: fg_primitives::SetId,441			_authority_id: GrandpaId,442		) -> Option<fg_primitives::OpaqueKeyOwnershipProof> {443			// NOTE: this is the only implementation possible since we've444			// defined our key owner proof type as a bottom type (i.e. a type445			// with no values).446			None447		}448	}449450	impl contracts_rpc_runtime_api::ContractsApi<Block, AccountId, Balance, BlockNumber>451	for Runtime452	{453		fn call(454			origin: AccountId,455			dest: AccountId,456			value: Balance,457			gas_limit: u64,458			input_data: Vec<u8>,459		) -> ContractExecResult {460			let exec_result =461				Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);462			match exec_result {463				Ok(v) => ContractExecResult::Success {464					status: v.status,465					data: v.data,466				},467				Err(_) => ContractExecResult::Error,468			}469		}470471		fn get_storage(472			address: AccountId,473			key: [u8; 32],474		) -> contracts_primitives::GetStorageResult {475			Contracts::get_storage(address, key)476		}477478		fn rent_projection(479			address: AccountId,480		) -> contracts_primitives::RentProjectionResult<BlockNumber> {481			Contracts::rent_projection(address)482		}483	}484485}