diff --git a/pallets/contracts/src/benchmarking.rs b/pallets/contracts/src/benchmarking.rs index c591878473..4d6b599bcf 100644 --- a/pallets/contracts/src/benchmarking.rs +++ b/pallets/contracts/src/benchmarking.rs @@ -28,12 +28,11 @@ use sp_runtime::Perbill; use sp_std::prelude::*; use wasm_instrument::parity_wasm::elements::{Instruction, ValueType}; -use polymesh_common_utilities::{ - benchs::{cdd_provider, user, AccountIdOf, User}, - constants::currency::POLY, - group::GroupTrait, - TestUtilsFn, -}; +use pallet_identity::ParentDid; +use polymesh_common_utilities::benchs::{cdd_provider, user, AccountIdOf, User, UserBuilder}; +use polymesh_common_utilities::constants::currency::POLY; +use polymesh_common_utilities::group::GroupTrait; +use polymesh_common_utilities::TestUtilsFn; use polymesh_primitives::identity::limits::{ MAX_ASSETS, MAX_EXTRINSICS, MAX_PALLETS, MAX_PORTFOLIOS, }; @@ -73,7 +72,7 @@ where // Check if contact is already linked. match Identity::::get_identity(&contract) { Some(contract_did) => { - if contract_did != did { + if contract_did != did && ParentDid::get(contract_did) != Some(did) { // Contract address already linked to a different identity. Err(IdentityError::::AlreadyLinked.into()) } else { @@ -188,8 +187,13 @@ where T::AccountId: UncheckedFrom + AsRef<[u8]>, { pub fn new(wasm: WasmModule) -> Self { - // Construct a user. - let caller = funded_user::(SEED); + // Construct a user + let caller = UserBuilder::::default() + .seed(SEED) + .generate_did() + .become_cdd_provider() + .build("Caller"); + T::Currency::make_free_balance_be(&caller.account(), 1_000_000 * POLY); // Instantiate the contract. let account_id = instantiate::(&caller, wasm, salt()); @@ -523,4 +527,40 @@ benchmarks! { .map(|id| ([(id & 0xFF) as u8, (id >> 8) as u8].into(), true)) .collect(); }: _(RawOrigin::Root, updates) + + instantiate_with_code_as_primary_key { + let c in 0 .. Perbill::from_percent(49).mul_ceil(T::MaxCodeLen::get()); + let s in 0 .. max_pages::() * 64 * 1024; + + let alice = UserBuilder::::default() + .generate_did() + .become_cdd_provider() + .build("Alice"); + T::Currency::make_free_balance_be(&alice.account(), 1_000_000 * POLY); + + let salt = vec![42u8; s as usize]; + let wasm = WasmModule::::sized(c, Location::Deploy); + let addr = FrameContracts::::contract_address(&alice.account(), &wasm.hash, &[], &salt); + }: _(alice.origin(), ENDOWMENT, Weight::MAX, None, wasm.code, vec![], salt) + verify { + assert_eq!(free_balance::(&addr), ENDOWMENT + 1 as Balance); + } + + instantiate_with_hash_as_primary_key { + let s in 0 .. max_pages::() * 64 * 1024; + let salt = vec![42u8; s as usize]; + + let wasm = WasmModule::::dummy(); + let hash = wasm.hash.clone(); + + // Pre-instantiate a contract so that one with the hash exists. + let contract = Contract::::new(wasm); + let user = contract.caller; + + // Calculate new contract's address. + let addr = FrameContracts::::contract_address(&user.account(), &hash, &[], &salt); + }: _(user.origin(), ENDOWMENT, Weight::MAX, None, hash, vec![], salt) + verify { + assert_eq!(free_balance::(&addr), ENDOWMENT + 1 as Balance); + } } diff --git a/pallets/contracts/src/lib.rs b/pallets/contracts/src/lib.rs index f5e0bea2a4..2eb40f2fec 100644 --- a/pallets/contracts/src/lib.rs +++ b/pallets/contracts/src/lib.rs @@ -72,11 +72,10 @@ use sp_std::{vec, vec::Vec}; use pallet_contracts::Config as BConfig; use pallet_contracts_primitives::{Code, ContractResult}; -use pallet_identity::PermissionedCallOriginData; +use pallet_identity::ParentDid; use polymesh_common_utilities::traits::identity::{ Config as IdentityConfig, WeightInfo as IdentityWeightInfo, }; -use polymesh_common_utilities::with_transaction; use polymesh_primitives::{storage_migrate_on, storage_migration_ver, Balance, Permissions}; type Identity = pallet_identity::Module; @@ -102,7 +101,7 @@ where // Check if contact is already linked. match Identity::::get_identity(&contract) { Some(contract_did) => { - if contract_did != did { + if contract_did != did && ParentDid::get(contract_did) != Some(did) { // Contract address already linked to a different identity. Err(IdentityError::::AlreadyLinked.into()) } else { @@ -157,6 +156,8 @@ pub trait WeightInfo { fn chain_extension_call_runtime(n: u32) -> Weight; fn dummy_contract() -> Weight; fn basic_runtime_call(n: u32) -> Weight; + fn instantiate_with_code_as_primary_key(code_len: u32, salt_len: u32) -> Weight; + fn instantiate_with_hash_as_primary_key(salt_len: u32) -> Weight; /// Computes the cost of instantiating where `code_len` /// and `salt_len` are specified in kilobytes. @@ -264,6 +265,10 @@ decl_error! { InstantiatorWithNoIdentity, /// Extrinsic is not allowed to be called by contracts. RuntimeCallDenied, + /// The caller is not a primary key. + CallerNotAPrimaryKey, + /// Secondary key permissions are missing. + MissingKeyPermissions } } @@ -333,7 +338,7 @@ decl_module! { /// - All the errors in `pallet_contracts::Call::instantiate_with_code` can also happen here. /// - CDD/Permissions are checked, unlike in `pallet_contracts`. /// - Errors that arise when adding a new secondary key can also occur here. - #[weight = Module::::weight_instantiate_with_code(&code, &salt, &perms).saturating_add(*gas_limit)] + #[weight = Module::::weight_instantiate_with_code(&code, &salt, Some(perms)).saturating_add(*gas_limit)] pub fn instantiate_with_code_perms( origin, endowment: Balance, @@ -344,7 +349,17 @@ decl_module! { salt: Vec, perms: Permissions ) -> DispatchResultWithPostInfo { - Self::base_instantiate_with_code(origin, endowment, gas_limit, storage_deposit_limit, code, data, salt, perms) + Self::base_instantiate_with_code( + origin, + endowment, + gas_limit, + storage_deposit_limit, + code, + data, + salt, + Some(perms), + false + ) } /// Instantiates a smart contract defining using the given `code_hash` and `salt`. @@ -374,7 +389,7 @@ decl_module! { /// - All the errors in `pallet_contracts::Call::instantiate` can also happen here. /// - CDD/Permissions are checked, unlike in `pallet_contracts`. /// - Errors that arise when adding a new secondary key can also occur here. - #[weight = Module::::weight_instantiate_with_hash(&salt, &perms).saturating_add(*gas_limit)] + #[weight = Module::::weight_instantiate_with_hash(&salt, Some(perms)).saturating_add(*gas_limit)] pub fn instantiate_with_hash_perms( origin, endowment: Balance, @@ -385,7 +400,17 @@ decl_module! { salt: Vec, perms: Permissions ) -> DispatchResultWithPostInfo { - Self::base_instantiate_with_hash(origin, endowment, gas_limit, storage_deposit_limit, code_hash, data, salt, perms) + Self::base_instantiate_with_hash( + origin, + endowment, + gas_limit, + storage_deposit_limit, + code_hash, + data, + salt, + Some(perms), + false + ) } /// Update CallRuntime whitelist. @@ -397,6 +422,78 @@ decl_module! { pub fn update_call_runtime_whitelist(origin, updates: Vec<(ExtrinsicId, bool)>) -> DispatchResult { Self::base_update_call_runtime_whitelist(origin, updates) } + + /// Instantiates a smart contract defining it with the given `code` and `salt`. + /// + /// The contract will be attached as a primary key of a newly created child identity of the caller. + /// + /// # Arguments + /// - `endowment`: Amount of POLYX to transfer to the contract. + /// - `gas_limit`: For how much gas the `deploy` code in the contract may at most consume. + /// - `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved from the caller to pay for the storage consumed. + /// - `code`: The WASM binary defining the smart contract. + /// - `data`: The input data to pass to the contract constructor. + /// - `salt`: Used for contract address derivation. By varying this, the same `code` can be used under the same identity. + /// + #[weight = Module::::weight_instantiate_with_code(&code, &salt, None).saturating_add(*gas_limit)] + pub fn instantiate_with_code_as_primary_key( + origin, + endowment: Balance, + gas_limit: Weight, + storage_deposit_limit: Option, + code: Vec, + data: Vec, + salt: Vec + ) -> DispatchResultWithPostInfo { + Self::base_instantiate_with_code( + origin, + endowment, + gas_limit, + storage_deposit_limit, + code, + data, + salt, + None, + true + ) + } + + /// Instantiates a smart contract defining using the given `code_hash` and `salt`. + /// + /// Unlike `instantiate_with_code`, this assumes that at least one contract with the same WASM code has already been uploaded. + /// + /// The contract will be attached as a primary key of a newly created child identity of the caller. + /// + /// # Arguments + /// - `endowment`: amount of POLYX to transfer to the contract. + /// - `gas_limit`: for how much gas the `deploy` code in the contract may at most consume. + /// - `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved from the caller to pay for the storage consumed. + /// - `code_hash`: of an already uploaded WASM binary. + /// - `data`: The input data to pass to the contract constructor. + /// - `salt`: used for contract address derivation. By varying this, the same `code` can be used under the same identity. + /// + #[weight = Module::::weight_instantiate_with_hash(&salt, None).saturating_add(*gas_limit)] + pub fn instantiate_with_hash_as_primary_key( + origin, + endowment: Balance, + gas_limit: Weight, + storage_deposit_limit: Option, + code_hash: CodeHash, + data: Vec, + salt: Vec, + ) -> DispatchResultWithPostInfo { + Self::base_instantiate_with_hash( + origin, + endowment, + gas_limit, + storage_deposit_limit, + code_hash, + data, + salt, + None, + true + ) + } } } @@ -438,27 +535,40 @@ where code: Vec, inst_data: Vec, salt: Vec, - perms: Permissions, + perms: Option, + deploy_as_child_identity: bool, ) -> DispatchResultWithPostInfo { Self::general_instantiate( origin, endowment, - // Compute the base weight of roughly `base_instantiate`. - Self::weight_instantiate_with_code(&code, &salt, &perms), + Self::weight_instantiate_with_code(&code, &salt, perms.as_ref()), gas_limit, storage_deposit_limit, Code::Upload(code), inst_data, salt, perms, + deploy_as_child_identity, ) } - /// Computes weight of `instantiate_with_code(code, salt, perms)`. - fn weight_instantiate_with_code(code: &[u8], salt: &[u8], perms: &Permissions) -> Weight { - ::WeightInfo::instantiate_with_code_bytes(&code, &salt).saturating_add( - ::WeightInfo::permissions_cost_perms(perms), - ) + /// Computes the weight of `instantiate_with_code(code, salt, perms)`. + fn weight_instantiate_with_code( + code: &[u8], + salt: &[u8], + perms: Option<&Permissions>, + ) -> Weight { + match perms { + Some(permissions) => { + ::WeightInfo::instantiate_with_code_bytes(&code, &salt).saturating_add( + ::WeightInfo::permissions_cost_perms(permissions), + ) + } + None => ::WeightInfo::instantiate_with_code_as_primary_key( + code.len() as u32, + salt.len() as u32, + ), + } } /// Instantiates a contract using an existing WASM code blob with `code_hash` as its code. @@ -470,27 +580,35 @@ where code_hash: CodeHash, inst_data: Vec, salt: Vec, - perms: Permissions, + perms: Option, + deploy_as_child_identity: bool, ) -> DispatchResultWithPostInfo { Self::general_instantiate( origin, endowment, // Compute the base weight of roughly `base_instantiate`. - Self::weight_instantiate_with_hash(&salt, &perms), + Self::weight_instantiate_with_hash(&salt, perms.as_ref()), gas_limit, storage_deposit_limit, Code::Existing(code_hash), inst_data, salt, perms, + deploy_as_child_identity, ) } - /// Computes weight of `instantiate_with_hash(code, salt, perms)`. - fn weight_instantiate_with_hash(salt: &[u8], perms: &Permissions) -> Weight { - ::WeightInfo::instantiate_with_hash_bytes(&salt).saturating_add( - ::WeightInfo::permissions_cost_perms(perms), - ) + /// Computes weight of `instantiate_with_hash(salt, perms)`. + fn weight_instantiate_with_hash(salt: &[u8], perms: Option<&Permissions>) -> Weight { + match perms { + Some(permissions) => ::WeightInfo::instantiate_with_hash_bytes(&salt) + .saturating_add(::WeightInfo::permissions_cost_perms( + permissions, + )), + None => { + ::WeightInfo::instantiate_with_hash_as_primary_key(salt.len() as u32) + } + } } /// General logic for contract instantiation both when the code or code hash is given. @@ -509,46 +627,51 @@ where code: Code>, inst_data: Vec, salt: Vec, - perms: Permissions, + perms: Option, + deploy_as_child_identity: bool, ) -> DispatchResultWithPostInfo { // Ensure we have perms + we'll need sender & DID. - let PermissionedCallOriginData { - primary_did: did, - sender, - .. - } = Identity::::ensure_origin_call_permissions(origin)?; + let origin_data = Identity::::ensure_origin_call_permissions(origin)?; - // Pre-compute what contract's key will be... + // Pre-compute what contract's key will be let contract_key = FrameContracts::::contract_address( - &sender, + &origin_data.sender, &Self::code_hash(&code), &inst_data, &salt, ); - // ...and ensure that key can be a secondary-key of DID... - Identity::::ensure_perms_length_limited(&perms)?; + // Ensure contract_key is not linked to a DID Identity::::ensure_key_did_unlinked(&contract_key)?; - - with_transaction(|| { + if !deploy_as_child_identity { + let perms = perms.ok_or(Error::::MissingKeyPermissions)?; + // Ensure that the key can be a secondary-key + Identity::::ensure_perms_length_limited(&perms)?; // Link contract's address to caller's identity as a secondary key with `perms`. - Identity::::unsafe_join_identity(did, perms, contract_key); - - // Now we can finally instantiate the contract. - Self::handle_error( - base_weight, - FrameContracts::::bare_instantiate( - sender, - endowment, - gas_limit, - storage_deposit_limit, - code, - inst_data, - salt, - false, - ), - ) - }) + Identity::::unsafe_join_identity(origin_data.primary_did, perms, contract_key); + } else { + ensure!( + origin_data.secondary_key.is_none(), + Error::::CallerNotAPrimaryKey + ); + Identity::::ensure_no_parent(origin_data.primary_did)?; + Identity::::unverified_create_child_identity(contract_key, origin_data.primary_did)?; + } + + // Instantiate the contract. + Self::handle_error( + base_weight, + FrameContracts::::bare_instantiate( + origin_data.sender, + endowment, + gas_limit, + storage_deposit_limit, + code, + inst_data, + salt, + false, + ), + ) } /// Computes the code hash of `code`. diff --git a/pallets/identity/src/keys.rs b/pallets/identity/src/keys.rs index 2df244bf96..223b8548a3 100644 --- a/pallets/identity/src/keys.rs +++ b/pallets/identity/src/keys.rs @@ -446,11 +446,6 @@ impl Module { // Ensure that the key can be unlinked. Self::ensure_key_unlinkable_from_did(&secondary_key)?; - T::ProtocolFee::charge_fee(ProtocolOp::IdentityCreateChildIdentity)?; - - // Generate a new DID for the child. - let child_did = Self::make_did()?; - // Unlink the secondary account key. Self::remove_key_record(&secondary_key, Some(parent_did)); Self::deposit_event(RawEvent::SecondaryKeysRemoved( @@ -458,20 +453,27 @@ impl Module { vec![secondary_key.clone()], )); - let primary_key = secondary_key; - // Create a new identity record and link the primary key. - Self::add_key_record(&primary_key, KeyRecord::PrimaryKey(child_did)); - Self::deposit_event(RawEvent::DidCreated(child_did, primary_key.clone(), vec![])); + // Creates a child identity and sets `secondary_key` as the child's primary key + Self::unverified_create_child_identity(secondary_key, parent_did)?; + + Ok(()) + } + /// Creates a new child identity for `parent_did` setting `key` as the primary key for the new identity. + pub fn unverified_create_child_identity( + key: T::AccountId, + parent_did: IdentityId, + ) -> DispatchResult { + T::ProtocolFee::charge_fee(ProtocolOp::IdentityCreateChildIdentity)?; + // Generate a new DID for the child. + let child_did = Self::make_did()?; + // Create a new identity record + Self::add_key_record(&key, KeyRecord::PrimaryKey(child_did)); + Self::deposit_event(RawEvent::DidCreated(child_did, key.clone(), vec![])); // Link new identity to parent identity. ParentDid::insert(child_did, parent_did); - Self::deposit_event(RawEvent::ChildDidCreated( - parent_did, - child_did, - primary_key, - )); - + Self::deposit_event(RawEvent::ChildDidCreated(parent_did, child_did, key)); Ok(()) } diff --git a/pallets/runtime/tests/src/contracts_test.rs b/pallets/runtime/tests/src/contracts_test.rs index 26a4d953d7..22ad26013c 100644 --- a/pallets/runtime/tests/src/contracts_test.rs +++ b/pallets/runtime/tests/src/contracts_test.rs @@ -1,16 +1,18 @@ -use crate::{ - ext_builder::ExtBuilder, - storage::{TestStorage, User}, -}; use codec::Encode; +use frame_support::dispatch::Weight; use frame_support::{ - assert_err_ignore_postinfo, assert_noop, assert_ok, assert_storage_noop, dispatch::Weight, + assert_err_ignore_postinfo, assert_noop, assert_ok, assert_storage_noop, StorageMap, }; +use sp_keyring::AccountKeyring; +use sp_runtime::traits::Hash; + +use pallet_identity::ParentDid; use polymesh_common_utilities::constants::currency::POLY; use polymesh_primitives::{AccountId, Gas, Permissions, PortfolioPermissions, Ticker}; use polymesh_runtime_common::Currency; -use sp_keyring::AccountKeyring; -use sp_runtime::traits::Hash; + +use crate::ext_builder::ExtBuilder; +use crate::storage::{TestStorage, User}; // We leave it to tests in the substrate to ensure that `pallet-contracts` // is functioning correctly, so we do not add such redundant tests @@ -172,3 +174,50 @@ fn misc_polymesh_extensions() { assert_ok!(Asset::ensure_owner(&ticker, owner.did)); }) } + +#[test] +fn deploy_as_child_identity() { + let eve = AccountKeyring::Eve.to_account_id(); + ExtBuilder::default() + .cdd_providers(vec![eve.clone()]) + .adjust(Box::new(move |storage| { + polymesh_contracts::GenesisConfig { + call_whitelist: [ + [0x1A, 0x00], + [0x1A, 0x01], + [0x1A, 0x02], + [0x1A, 0x03], + [0x1A, 0x11], + [0x2F, 0x01], + ] + .into_iter() + .map(|ext_id: [u8; 2]| ext_id.into()) + .collect(), + } + .assimilate_storage(storage) + .unwrap(); + })) + .build() + .execute_with(|| { + let salt = vec![0xFF]; + let (code, _) = chain_extension(); + let hash = Hashing::hash(&code); + let alice = User::new(AccountKeyring::Alice); + Balances::make_free_balance_be(&alice.acc(), 1_000_000 * POLY); + + assert_ok!(Contracts::instantiate_with_code_as_primary_key( + alice.origin(), + Balances::minimum_balance(), + GAS_LIMIT, + None, + code.clone(), + vec![], + salt.clone(), + )); + + let contract_account_id = + FrameContracts::contract_address(&alice.acc(), &hash, &[], &salt); + let child_id = Identity::get_identity(&contract_account_id).unwrap(); + assert_eq!(ParentDid::get(child_id), Some(alice.did)); + }) +} diff --git a/pallets/weights/src/polymesh_contracts.rs b/pallets/weights/src/polymesh_contracts.rs index 05b573c5d3..d1ea17e470 100644 --- a/pallets/weights/src/polymesh_contracts.rs +++ b/pallets/weights/src/polymesh_contracts.rs @@ -453,4 +453,95 @@ impl polymesh_contracts::WeightInfo for SubstrateWeight { .saturating_add(Weight::from_ref_time(2_571_524).saturating_mul(u.into())) .saturating_add(DbWeight::get().writes((1_u64).saturating_mul(u.into()))) } + // Storage: Identity KeyRecords (r:3 w:1) + // Proof Skipped: Identity KeyRecords (max_values: None, max_size: None, mode: Measured) + // Storage: Identity ParentDid (r:1 w:1) + // Proof Skipped: Identity ParentDid (max_values: None, max_size: None, mode: Measured) + // Storage: ProtocolFee Coefficient (r:1 w:0) + // Proof Skipped: ProtocolFee Coefficient (max_values: Some(1), max_size: None, mode: Measured) + // Storage: ProtocolFee BaseFees (r:1 w:0) + // Proof Skipped: ProtocolFee BaseFees (max_values: None, max_size: None, mode: Measured) + // Storage: Identity MultiPurposeNonce (r:1 w:1) + // Proof Skipped: Identity MultiPurposeNonce (max_values: Some(1), max_size: None, mode: Measured) + // Storage: System ParentHash (r:1 w:0) + // Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + // Storage: Identity DidRecords (r:1 w:1) + // Proof Skipped: Identity DidRecords (max_values: None, max_size: None, mode: Measured) + // Storage: Contracts OwnerInfoOf (r:1 w:1) + // Proof: Contracts OwnerInfoOf (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + // Storage: System Account (r:3 w:3) + // Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Storage: Contracts Nonce (r:1 w:1) + // Proof: Contracts Nonce (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Proof: Contracts ContractInfoOf (max_values: None, max_size: Some(290), added: 2765, mode: MaxEncodedLen) + // Storage: Timestamp Now (r:1 w:0) + // Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + // Storage: Instance2Group ActiveMembers (r:1 w:0) + // Proof Skipped: Instance2Group ActiveMembers (max_values: Some(1), max_size: None, mode: Measured) + // Storage: Identity Claims (r:3 w:0) + // Proof Skipped: Identity Claims (max_values: None, max_size: None, mode: Measured) + // Storage: System EventTopics (r:3 w:3) + // Proof Skipped: System EventTopics (max_values: None, max_size: None, mode: Measured) + // Storage: Identity DidKeys (r:0 w:1) + // Proof Skipped: Identity DidKeys (max_values: None, max_size: None, mode: Measured) + // Storage: Contracts CodeStorage (r:0 w:1) + // Proof: Contracts CodeStorage (max_values: None, max_size: Some(126001), added: 128476, mode: MaxEncodedLen) + // Storage: Contracts PristineCode (r:0 w:1) + // Proof: Contracts PristineCode (max_values: None, max_size: Some(125988), added: 128463, mode: MaxEncodedLen) + /// The range of component `c` is `[0, 61717]`. + /// The range of component `s` is `[0, 1048576]`. + fn instantiate_with_code_as_primary_key(c: u32, s: u32) -> Weight { + // Minimum execution time: 4_335_262 nanoseconds. + Weight::from_ref_time(622_167_188) + // Standard Error: 340 + .saturating_add(Weight::from_ref_time(134_179).saturating_mul(c.into())) + // Standard Error: 20 + .saturating_add(Weight::from_ref_time(3_699).saturating_mul(s.into())) + .saturating_add(DbWeight::get().reads(23)) + .saturating_add(DbWeight::get().writes(16)) + } + // Storage: Identity KeyRecords (r:3 w:1) + // Proof Skipped: Identity KeyRecords (max_values: None, max_size: None, mode: Measured) + // Storage: Identity ParentDid (r:1 w:1) + // Proof Skipped: Identity ParentDid (max_values: None, max_size: None, mode: Measured) + // Storage: ProtocolFee Coefficient (r:1 w:0) + // Proof Skipped: ProtocolFee Coefficient (max_values: Some(1), max_size: None, mode: Measured) + // Storage: ProtocolFee BaseFees (r:1 w:0) + // Proof Skipped: ProtocolFee BaseFees (max_values: None, max_size: None, mode: Measured) + // Storage: Identity MultiPurposeNonce (r:1 w:1) + // Proof Skipped: Identity MultiPurposeNonce (max_values: Some(1), max_size: None, mode: Measured) + // Storage: System ParentHash (r:1 w:0) + // Proof: System ParentHash (max_values: Some(1), max_size: Some(32), added: 527, mode: MaxEncodedLen) + // Storage: Identity DidRecords (r:1 w:1) + // Proof Skipped: Identity DidRecords (max_values: None, max_size: None, mode: Measured) + // Storage: Contracts CodeStorage (r:1 w:0) + // Proof: Contracts CodeStorage (max_values: None, max_size: Some(126001), added: 128476, mode: MaxEncodedLen) + // Storage: System Account (r:3 w:3) + // Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + // Storage: Contracts Nonce (r:1 w:1) + // Proof: Contracts Nonce (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + // Storage: Contracts ContractInfoOf (r:1 w:1) + // Proof: Contracts ContractInfoOf (max_values: None, max_size: Some(290), added: 2765, mode: MaxEncodedLen) + // Storage: Timestamp Now (r:1 w:0) + // Proof: Timestamp Now (max_values: Some(1), max_size: Some(8), added: 503, mode: MaxEncodedLen) + // Storage: Instance2Group ActiveMembers (r:1 w:0) + // Proof Skipped: Instance2Group ActiveMembers (max_values: Some(1), max_size: None, mode: Measured) + // Storage: Identity Claims (r:3 w:0) + // Proof Skipped: Identity Claims (max_values: None, max_size: None, mode: Measured) + // Storage: Contracts OwnerInfoOf (r:1 w:1) + // Proof: Contracts OwnerInfoOf (max_values: None, max_size: Some(88), added: 2563, mode: MaxEncodedLen) + // Storage: System EventTopics (r:2 w:2) + // Proof Skipped: System EventTopics (max_values: None, max_size: None, mode: Measured) + // Storage: Identity DidKeys (r:0 w:1) + // Proof Skipped: Identity DidKeys (max_values: None, max_size: None, mode: Measured) + /// The range of component `s` is `[0, 1048576]`. + fn instantiate_with_hash_as_primary_key(s: u32) -> Weight { + // Minimum execution time: 532_686 nanoseconds. + Weight::from_ref_time(514_127_182) + // Standard Error: 7 + .saturating_add(Weight::from_ref_time(3_623).saturating_mul(s.into())) + .saturating_add(DbWeight::get().reads(23)) + .saturating_add(DbWeight::get().writes(13)) + } }