1#![allow(rustdoc::private_intra_doc_links)]
87#![cfg_attr(not(feature = "std"), no_std)]
88#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "1024")]
89
90extern crate alloc;
91mod address;
92mod benchmarking;
93mod exec;
94mod gas;
95mod primitives;
96pub use primitives::*;
97
98mod schedule;
99mod storage;
100mod transient_storage;
101mod wasm;
102
103pub mod chain_extension;
104pub mod debug;
105pub mod migration;
106pub mod test_utils;
107pub mod weights;
108
109#[cfg(test)]
110mod tests;
111use crate::{
112 exec::{
113 AccountIdOf, ErrorOrigin, ExecError, Executable, Ext, Key, MomentOf, Stack as ExecStack,
114 },
115 gas::GasMeter,
116 storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager},
117 wasm::{CodeInfo, RuntimeCosts, WasmBlob},
118};
119use codec::{Codec, Decode, DecodeWithMemTracking, Encode, HasCompact, MaxEncodedLen};
120use core::fmt::Debug;
121use environmental::*;
122use frame_support::{
123 dispatch::{GetDispatchInfo, Pays, PostDispatchInfo, RawOrigin, WithPostDispatchInfo},
124 ensure,
125 traits::{
126 fungible::{Inspect, Mutate, MutateHold},
127 ConstU32, Contains, Get, Randomness, Time,
128 },
129 weights::{Weight, WeightMeter},
130 BoundedVec, DefaultNoBound, RuntimeDebugNoBound,
131};
132use frame_system::{
133 ensure_signed,
134 pallet_prelude::{BlockNumberFor, OriginFor},
135 EventRecord, Pallet as System,
136};
137use scale_info::TypeInfo;
138use smallvec::Array;
139use sp_runtime::{
140 traits::{BadOrigin, Convert, Dispatchable, Saturating, StaticLookup, Zero},
141 DispatchError, RuntimeDebug,
142};
143
144pub use crate::{
145 address::{AddressGenerator, DefaultAddressGenerator},
146 debug::Tracing,
147 exec::Frame,
148 migration::{MigrateSequence, Migration, NoopMigration},
149 pallet::*,
150 schedule::{InstructionWeights, Limits, Schedule},
151 wasm::Determinism,
152};
153pub use weights::WeightInfo;
154
155#[cfg(doc)]
156pub use crate::wasm::api_doc;
157
158type CodeHash<T> = <T as frame_system::Config>::Hash;
159type TrieId = BoundedVec<u8, ConstU32<128>>;
160type BalanceOf<T> =
161 <<T as Config>::Currency as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
162type CodeVec<T> = BoundedVec<u8, <T as Config>::MaxCodeLen>;
163type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
164type DebugBufferVec<T> = BoundedVec<u8, <T as Config>::MaxDebugBufferLen>;
165type EventRecordOf<T> =
166 EventRecord<<T as frame_system::Config>::RuntimeEvent, <T as frame_system::Config>::Hash>;
167
168type OldWeight = u64;
173
174const SENTINEL: u32 = u32::MAX;
181
182const LOG_TARGET: &str = "runtime::contracts";
188
189#[derive(Encode, Decode, DefaultNoBound, TypeInfo)]
195#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
196pub struct EnvironmentType<T>(PhantomData<T>);
197
198#[derive(Encode, Decode, DefaultNoBound, TypeInfo)]
208#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
209#[scale_info(skip_type_params(T))]
210pub struct Environment<T: Config> {
211 account_id: EnvironmentType<AccountIdOf<T>>,
212 balance: EnvironmentType<BalanceOf<T>>,
213 hash: EnvironmentType<<T as frame_system::Config>::Hash>,
214 hasher: EnvironmentType<<T as frame_system::Config>::Hashing>,
215 timestamp: EnvironmentType<MomentOf<T>>,
216 block_number: EnvironmentType<BlockNumberFor<T>>,
217}
218
219#[derive(Encode, Decode, TypeInfo)]
224pub struct ApiVersion(u16);
225impl Default for ApiVersion {
226 fn default() -> Self {
227 Self(4)
228 }
229}
230
231#[test]
232fn api_version_is_up_to_date() {
233 assert_eq!(
234 111,
235 crate::wasm::STABLE_API_COUNT,
236 "Stable API count has changed. Bump the returned value of ApiVersion::default() and update the test."
237 );
238}
239
240#[frame_support::pallet]
241pub mod pallet {
242 use super::*;
243 use crate::debug::Debugger;
244 use frame_support::pallet_prelude::*;
245 use frame_system::pallet_prelude::*;
246 use sp_runtime::Perbill;
247
248 pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(16);
250
251 #[pallet::pallet]
252 #[pallet::storage_version(STORAGE_VERSION)]
253 pub struct Pallet<T>(_);
254
255 #[pallet::config(with_default)]
256 pub trait Config: frame_system::Config {
257 type Time: Time;
259
260 #[pallet::no_default_bounds]
269 type Randomness: Randomness<Self::Hash, BlockNumberFor<Self>>;
270
271 #[pallet::no_default]
273 type Currency: Inspect<Self::AccountId>
274 + Mutate<Self::AccountId>
275 + MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>;
276
277 #[pallet::no_default_bounds]
279 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
280
281 #[pallet::no_default_bounds]
283 type RuntimeCall: Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
284 + GetDispatchInfo
285 + codec::Decode
286 + IsType<<Self as frame_system::Config>::RuntimeCall>;
287
288 #[pallet::no_default_bounds]
290 type RuntimeHoldReason: From<HoldReason>;
291
292 #[pallet::no_default_bounds]
315 type CallFilter: Contains<<Self as frame_system::Config>::RuntimeCall>;
316
317 #[pallet::no_default_bounds]
320 type WeightPrice: Convert<Weight, BalanceOf<Self>>;
321
322 type WeightInfo: WeightInfo;
325
326 #[pallet::no_default_bounds]
328 type ChainExtension: chain_extension::ChainExtension<Self> + Default;
329
330 #[pallet::constant]
332 #[pallet::no_default]
333 type Schedule: Get<Schedule<Self>>;
334
335 #[pallet::no_default]
344 type CallStack: Array<Item = Frame<Self>>;
345
346 #[pallet::constant]
352 #[pallet::no_default_bounds]
353 type DepositPerByte: Get<BalanceOf<Self>>;
354
355 #[pallet::constant]
357 #[pallet::no_default_bounds]
358 type DefaultDepositLimit: Get<BalanceOf<Self>>;
359
360 #[pallet::constant]
366 #[pallet::no_default_bounds]
367 type DepositPerItem: Get<BalanceOf<Self>>;
368
369 #[pallet::constant]
374 type CodeHashLockupDepositPercent: Get<Perbill>;
375
376 #[pallet::no_default_bounds]
378 type AddressGenerator: AddressGenerator<Self>;
379
380 #[pallet::constant]
386 type MaxCodeLen: Get<u32>;
387
388 #[pallet::constant]
390 type MaxStorageKeyLen: Get<u32>;
391
392 #[pallet::constant]
395 type MaxTransientStorageSize: Get<u32>;
396
397 #[pallet::constant]
400 type MaxDelegateDependencies: Get<u32>;
401
402 #[pallet::constant]
412 type UnsafeUnstableInterface: Get<bool>;
413
414 #[pallet::constant]
416 type MaxDebugBufferLen: Get<u32>;
417
418 #[pallet::no_default_bounds]
423 type UploadOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
424
425 #[pallet::no_default_bounds]
436 type InstantiateOrigin: EnsureOrigin<Self::RuntimeOrigin, Success = Self::AccountId>;
437
438 type Migrations: MigrateSequence;
456
457 #[pallet::no_default_bounds]
462 type Debug: Debugger<Self>;
463
464 #[pallet::constant]
469 #[pallet::no_default_bounds]
470 type Environment: Get<Environment<Self>>;
471
472 #[pallet::constant]
476 #[pallet::no_default_bounds]
477 type ApiVersion: Get<ApiVersion>;
478
479 #[pallet::no_default_bounds]
482 type Xcm: xcm_builder::Controller<
483 OriginFor<Self>,
484 <Self as frame_system::Config>::RuntimeCall,
485 BlockNumberFor<Self>,
486 >;
487 }
488
489 pub mod config_preludes {
491 use super::*;
492 use frame_support::{
493 derive_impl,
494 traits::{ConstBool, ConstU32},
495 };
496 use frame_system::EnsureSigned;
497 use sp_core::parameter_types;
498
499 type AccountId = sp_runtime::AccountId32;
500 type Balance = u64;
501 const UNITS: Balance = 10_000_000_000;
502 const CENTS: Balance = UNITS / 100;
503
504 const fn deposit(items: u32, bytes: u32) -> Balance {
505 items as Balance * 1 * CENTS + (bytes as Balance) * 1 * CENTS
506 }
507
508 parameter_types! {
509 pub const DepositPerItem: Balance = deposit(1, 0);
510 pub const DepositPerByte: Balance = deposit(0, 1);
511 pub const DefaultDepositLimit: Balance = deposit(1024, 1024 * 1024);
512 pub const CodeHashLockupDepositPercent: Perbill = Perbill::from_percent(0);
513 pub const MaxDelegateDependencies: u32 = 32;
514 }
515
516 pub struct TestDefaultConfig;
518
519 impl<Output, BlockNumber> Randomness<Output, BlockNumber> for TestDefaultConfig {
520 fn random(_subject: &[u8]) -> (Output, BlockNumber) {
521 unimplemented!("No default `random` implementation in `TestDefaultConfig`, provide a custom `T::Randomness` type.")
522 }
523 }
524
525 impl Time for TestDefaultConfig {
526 type Moment = u64;
527 fn now() -> Self::Moment {
528 unimplemented!("No default `now` implementation in `TestDefaultConfig` provide a custom `T::Time` type.")
529 }
530 }
531
532 impl<T: From<u64>> Convert<Weight, T> for TestDefaultConfig {
533 fn convert(w: Weight) -> T {
534 w.ref_time().into()
535 }
536 }
537
538 #[derive_impl(frame_system::config_preludes::TestDefaultConfig, no_aggregated_types)]
539 impl frame_system::DefaultConfig for TestDefaultConfig {}
540
541 #[frame_support::register_default_impl(TestDefaultConfig)]
542 impl DefaultConfig for TestDefaultConfig {
543 #[inject_runtime_type]
544 type RuntimeEvent = ();
545
546 #[inject_runtime_type]
547 type RuntimeHoldReason = ();
548
549 #[inject_runtime_type]
550 type RuntimeCall = ();
551
552 type AddressGenerator = DefaultAddressGenerator;
553 type CallFilter = ();
554 type ChainExtension = ();
555 type CodeHashLockupDepositPercent = CodeHashLockupDepositPercent;
556 type DefaultDepositLimit = DefaultDepositLimit;
557 type DepositPerByte = DepositPerByte;
558 type DepositPerItem = DepositPerItem;
559 type MaxCodeLen = ConstU32<{ 123 * 1024 }>;
560 type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>;
561 type MaxDelegateDependencies = MaxDelegateDependencies;
562 type MaxStorageKeyLen = ConstU32<128>;
563 type MaxTransientStorageSize = ConstU32<{ 1 * 1024 * 1024 }>;
564 type Migrations = ();
565 type Time = Self;
566 type Randomness = Self;
567 type UnsafeUnstableInterface = ConstBool<true>;
568 type UploadOrigin = EnsureSigned<AccountId>;
569 type InstantiateOrigin = EnsureSigned<AccountId>;
570 type WeightInfo = ();
571 type WeightPrice = Self;
572 type Debug = ();
573 type Environment = ();
574 type ApiVersion = ();
575 type Xcm = ();
576 }
577 }
578
579 #[pallet::hooks]
580 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
581 fn on_idle(_block: BlockNumberFor<T>, limit: Weight) -> Weight {
582 use migration::MigrateResult::*;
583 let mut meter = WeightMeter::with_limit(limit);
584
585 loop {
586 match Migration::<T>::migrate(&mut meter) {
587 NoMigrationPerformed | InProgress { steps_done: 0 } => return meter.consumed(),
590 InProgress { .. } => continue,
592 Completed | NoMigrationInProgress => break,
595 }
596 }
597
598 ContractInfo::<T>::process_deletion_queue_batch(&mut meter);
599 meter.consumed()
600 }
601
602 fn integrity_test() {
603 Migration::<T>::integrity_test();
604
605 let max_runtime_mem: u32 = T::Schedule::get().limits.runtime_memory;
607 const MAX_STACK_SIZE: u32 = 1024 * 1024;
610 let max_heap_size = T::Schedule::get().limits.max_memory_size();
612 let max_call_depth = u32::try_from(T::CallStack::size().saturating_add(1))
614 .expect("CallStack size is too big");
615 let max_transient_storage_size = T::MaxTransientStorageSize::get()
618 .checked_mul(2)
619 .expect("MaxTransientStorageSize is too large");
620 let code_len_limit = max_runtime_mem
650 .saturating_div(2)
651 .saturating_sub(max_transient_storage_size)
652 .saturating_div(max_call_depth)
653 .saturating_sub(max_heap_size)
654 .saturating_sub(MAX_STACK_SIZE)
655 .saturating_div(17 * 4);
656
657 assert!(
658 T::MaxCodeLen::get() < code_len_limit,
659 "Given `CallStack` height {:?}, `MaxCodeLen` should be set less than {:?} \
660 (current value is {:?}), to avoid possible runtime oom issues.",
661 max_call_depth,
662 code_len_limit,
663 T::MaxCodeLen::get(),
664 );
665
666 const MIN_DEBUG_BUF_SIZE: u32 = 256;
668 assert!(
669 T::MaxDebugBufferLen::get() > MIN_DEBUG_BUF_SIZE,
670 "Debug buffer should have minimum size of {} (current setting is {})",
671 MIN_DEBUG_BUF_SIZE,
672 T::MaxDebugBufferLen::get(),
673 );
674
675 let max_block_ref_time = T::BlockWeights::get()
681 .get(DispatchClass::Normal)
682 .max_total
683 .unwrap_or_else(|| T::BlockWeights::get().max_block)
684 .ref_time();
685 let max_payload_size = T::Schedule::get().limits.payload_len;
686 let max_key_size =
687 Key::<T>::try_from_var(alloc::vec![0u8; T::MaxStorageKeyLen::get() as usize])
688 .expect("Key of maximal size shall be created")
689 .hash()
690 .len() as u32;
691
692 let max_storage_size: u32 = ((max_block_ref_time /
695 (<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::SetStorage {
696 new_bytes: max_payload_size,
697 old_bytes: 0,
698 })
699 .ref_time()))
700 .saturating_mul(max_payload_size.saturating_add(max_key_size) as u64))
701 .try_into()
702 .expect("Storage size too big");
703
704 let max_validator_runtime_mem: u32 = T::Schedule::get().limits.validator_runtime_memory;
705 let storage_size_limit = max_validator_runtime_mem.saturating_sub(max_runtime_mem) / 2;
706
707 assert!(
708 max_storage_size < storage_size_limit,
709 "Maximal storage size {} exceeds the storage limit {}",
710 max_storage_size,
711 storage_size_limit
712 );
713
714 let max_events_size: u32 = ((max_block_ref_time /
718 (<RuntimeCosts as gas::Token<T>>::weight(&RuntimeCosts::DepositEvent {
719 num_topic: 0,
720 len: max_payload_size,
721 })
722 .ref_time()))
723 .saturating_mul(max_payload_size as u64))
724 .try_into()
725 .expect("Events size too big");
726
727 assert!(
728 max_events_size < storage_size_limit,
729 "Maximal events size {} exceeds the events limit {}",
730 max_events_size,
731 storage_size_limit
732 );
733 }
734 }
735
736 #[pallet::call]
737 impl<T: Config> Pallet<T>
738 where
739 <BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
740 {
741 #[pallet::call_index(0)]
743 #[pallet::weight(T::WeightInfo::call().saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit)))]
744 #[allow(deprecated)]
745 #[deprecated(note = "1D weight is used in this extrinsic, please migrate to `call`")]
746 pub fn call_old_weight(
747 origin: OriginFor<T>,
748 dest: AccountIdLookupOf<T>,
749 #[pallet::compact] value: BalanceOf<T>,
750 #[pallet::compact] gas_limit: OldWeight,
751 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
752 data: Vec<u8>,
753 ) -> DispatchResultWithPostInfo {
754 Self::call(
755 origin,
756 dest,
757 value,
758 <Pallet<T>>::compat_weight_limit(gas_limit),
759 storage_deposit_limit,
760 data,
761 )
762 }
763
764 #[pallet::call_index(1)]
766 #[pallet::weight(
767 T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
768 .saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit))
769 )]
770 #[allow(deprecated)]
771 #[deprecated(
772 note = "1D weight is used in this extrinsic, please migrate to `instantiate_with_code`"
773 )]
774 pub fn instantiate_with_code_old_weight(
775 origin: OriginFor<T>,
776 #[pallet::compact] value: BalanceOf<T>,
777 #[pallet::compact] gas_limit: OldWeight,
778 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
779 code: Vec<u8>,
780 data: Vec<u8>,
781 salt: Vec<u8>,
782 ) -> DispatchResultWithPostInfo {
783 Self::instantiate_with_code(
784 origin,
785 value,
786 <Pallet<T>>::compat_weight_limit(gas_limit),
787 storage_deposit_limit,
788 code,
789 data,
790 salt,
791 )
792 }
793
794 #[pallet::call_index(2)]
796 #[pallet::weight(
797 T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit))
798 )]
799 #[allow(deprecated)]
800 #[deprecated(note = "1D weight is used in this extrinsic, please migrate to `instantiate`")]
801 pub fn instantiate_old_weight(
802 origin: OriginFor<T>,
803 #[pallet::compact] value: BalanceOf<T>,
804 #[pallet::compact] gas_limit: OldWeight,
805 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
806 code_hash: CodeHash<T>,
807 data: Vec<u8>,
808 salt: Vec<u8>,
809 ) -> DispatchResultWithPostInfo {
810 Self::instantiate(
811 origin,
812 value,
813 <Pallet<T>>::compat_weight_limit(gas_limit),
814 storage_deposit_limit,
815 code_hash,
816 data,
817 salt,
818 )
819 }
820
821 #[pallet::call_index(3)]
846 #[pallet::weight(
847 match determinism {
848 Determinism::Enforced => T::WeightInfo::upload_code_determinism_enforced(code.len() as u32),
849 Determinism::Relaxed => T::WeightInfo::upload_code_determinism_relaxed(code.len() as u32),
850 }
851 )]
852 pub fn upload_code(
853 origin: OriginFor<T>,
854 code: Vec<u8>,
855 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
856 determinism: Determinism,
857 ) -> DispatchResult {
858 Migration::<T>::ensure_migrated()?;
859 let origin = T::UploadOrigin::ensure_origin(origin)?;
860 Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into), determinism)
861 .map(|_| ())
862 }
863
864 #[pallet::call_index(4)]
869 #[pallet::weight(T::WeightInfo::remove_code())]
870 pub fn remove_code(
871 origin: OriginFor<T>,
872 code_hash: CodeHash<T>,
873 ) -> DispatchResultWithPostInfo {
874 Migration::<T>::ensure_migrated()?;
875 let origin = ensure_signed(origin)?;
876 <WasmBlob<T>>::remove(&origin, code_hash)?;
877 Ok(Pays::No.into())
879 }
880
881 #[pallet::call_index(5)]
892 #[pallet::weight(T::WeightInfo::set_code())]
893 pub fn set_code(
894 origin: OriginFor<T>,
895 dest: AccountIdLookupOf<T>,
896 code_hash: CodeHash<T>,
897 ) -> DispatchResult {
898 Migration::<T>::ensure_migrated()?;
899 ensure_root(origin)?;
900 let dest = T::Lookup::lookup(dest)?;
901 <ContractInfoOf<T>>::try_mutate(&dest, |contract| {
902 let contract = if let Some(contract) = contract {
903 contract
904 } else {
905 return Err(<Error<T>>::ContractNotFound.into())
906 };
907 <ExecStack<T, WasmBlob<T>>>::increment_refcount(code_hash)?;
908 <ExecStack<T, WasmBlob<T>>>::decrement_refcount(contract.code_hash);
909 Self::deposit_event(Event::ContractCodeUpdated {
910 contract: dest.clone(),
911 new_code_hash: code_hash,
912 old_code_hash: contract.code_hash,
913 });
914 contract.code_hash = code_hash;
915 Ok(())
916 })
917 }
918
919 #[pallet::call_index(6)]
936 #[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
937 pub fn call(
938 origin: OriginFor<T>,
939 dest: AccountIdLookupOf<T>,
940 #[pallet::compact] value: BalanceOf<T>,
941 gas_limit: Weight,
942 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
943 data: Vec<u8>,
944 ) -> DispatchResultWithPostInfo {
945 Migration::<T>::ensure_migrated()?;
946 let common = CommonInput {
947 origin: Origin::from_runtime_origin(origin)?,
948 value,
949 data,
950 gas_limit: gas_limit.into(),
951 storage_deposit_limit: storage_deposit_limit.map(Into::into),
952 debug_message: None,
953 };
954 let dest = T::Lookup::lookup(dest)?;
955 let mut output =
956 CallInput::<T> { dest, determinism: Determinism::Enforced }.run_guarded(common);
957 if let Ok(retval) = &output.result {
958 if retval.did_revert() {
959 output.result = Err(<Error<T>>::ContractReverted.into());
960 }
961 }
962 output.gas_meter.into_dispatch_result(output.result, T::WeightInfo::call())
963 }
964
965 #[pallet::call_index(7)]
991 #[pallet::weight(
992 T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
993 .saturating_add(*gas_limit)
994 )]
995 pub fn instantiate_with_code(
996 origin: OriginFor<T>,
997 #[pallet::compact] value: BalanceOf<T>,
998 gas_limit: Weight,
999 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
1000 code: Vec<u8>,
1001 data: Vec<u8>,
1002 salt: Vec<u8>,
1003 ) -> DispatchResultWithPostInfo {
1004 Migration::<T>::ensure_migrated()?;
1005
1006 let upload_origin = T::UploadOrigin::ensure_origin(origin.clone())?;
1010 let instantiate_origin = T::InstantiateOrigin::ensure_origin(origin)?;
1011
1012 let code_len = code.len() as u32;
1013
1014 let (module, upload_deposit) = Self::try_upload_code(
1015 upload_origin,
1016 code,
1017 storage_deposit_limit.clone().map(Into::into),
1018 Determinism::Enforced,
1019 None,
1020 )?;
1021
1022 let storage_deposit_limit =
1024 storage_deposit_limit.map(|limit| limit.into().saturating_sub(upload_deposit));
1025
1026 let data_len = data.len() as u32;
1027 let salt_len = salt.len() as u32;
1028 let common = CommonInput {
1029 origin: Origin::from_account_id(instantiate_origin),
1030 value,
1031 data,
1032 gas_limit,
1033 storage_deposit_limit,
1034 debug_message: None,
1035 };
1036
1037 let mut output =
1038 InstantiateInput::<T> { code: WasmCode::Wasm(module), salt }.run_guarded(common);
1039 if let Ok(retval) = &output.result {
1040 if retval.1.did_revert() {
1041 output.result = Err(<Error<T>>::ContractReverted.into());
1042 }
1043 }
1044
1045 output.gas_meter.into_dispatch_result(
1046 output.result.map(|(_address, output)| output),
1047 T::WeightInfo::instantiate_with_code(code_len, data_len, salt_len),
1048 )
1049 }
1050
1051 #[pallet::call_index(8)]
1057 #[pallet::weight(
1058 T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(*gas_limit)
1059 )]
1060 pub fn instantiate(
1061 origin: OriginFor<T>,
1062 #[pallet::compact] value: BalanceOf<T>,
1063 gas_limit: Weight,
1064 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
1065 code_hash: CodeHash<T>,
1066 data: Vec<u8>,
1067 salt: Vec<u8>,
1068 ) -> DispatchResultWithPostInfo {
1069 Migration::<T>::ensure_migrated()?;
1070 let origin = T::InstantiateOrigin::ensure_origin(origin)?;
1071 let data_len = data.len() as u32;
1072 let salt_len = salt.len() as u32;
1073 let common = CommonInput {
1074 origin: Origin::from_account_id(origin),
1075 value,
1076 data,
1077 gas_limit,
1078 storage_deposit_limit: storage_deposit_limit.map(Into::into),
1079 debug_message: None,
1080 };
1081 let mut output = InstantiateInput::<T> { code: WasmCode::CodeHash(code_hash), salt }
1082 .run_guarded(common);
1083 if let Ok(retval) = &output.result {
1084 if retval.1.did_revert() {
1085 output.result = Err(<Error<T>>::ContractReverted.into());
1086 }
1087 }
1088 output.gas_meter.into_dispatch_result(
1089 output.result.map(|(_address, output)| output),
1090 T::WeightInfo::instantiate(data_len, salt_len),
1091 )
1092 }
1093
1094 #[pallet::call_index(9)]
1099 #[pallet::weight(T::WeightInfo::migrate().saturating_add(*weight_limit))]
1100 pub fn migrate(origin: OriginFor<T>, weight_limit: Weight) -> DispatchResultWithPostInfo {
1101 use migration::MigrateResult::*;
1102 ensure_signed(origin)?;
1103
1104 let weight_limit = weight_limit.saturating_add(T::WeightInfo::migrate());
1105 let mut meter = WeightMeter::with_limit(weight_limit);
1106 let result = Migration::<T>::migrate(&mut meter);
1107
1108 match result {
1109 Completed => Ok(PostDispatchInfo {
1110 actual_weight: Some(meter.consumed()),
1111 pays_fee: Pays::No,
1112 }),
1113 InProgress { steps_done, .. } if steps_done > 0 => Ok(PostDispatchInfo {
1114 actual_weight: Some(meter.consumed()),
1115 pays_fee: Pays::No,
1116 }),
1117 InProgress { .. } => Ok(PostDispatchInfo {
1118 actual_weight: Some(meter.consumed()),
1119 pays_fee: Pays::Yes,
1120 }),
1121 NoMigrationInProgress | NoMigrationPerformed => {
1122 let err: DispatchError = <Error<T>>::NoMigrationPerformed.into();
1123 Err(err.with_weight(meter.consumed()))
1124 },
1125 }
1126 }
1127 }
1128
1129 #[pallet::event]
1130 pub enum Event<T: Config> {
1131 Instantiated { deployer: T::AccountId, contract: T::AccountId },
1133
1134 Terminated {
1141 contract: T::AccountId,
1143 beneficiary: T::AccountId,
1145 },
1146
1147 CodeStored { code_hash: T::Hash, deposit_held: BalanceOf<T>, uploader: T::AccountId },
1149
1150 ContractEmitted {
1152 contract: T::AccountId,
1154 data: Vec<u8>,
1157 },
1158
1159 CodeRemoved { code_hash: T::Hash, deposit_released: BalanceOf<T>, remover: T::AccountId },
1161
1162 ContractCodeUpdated {
1164 contract: T::AccountId,
1166 new_code_hash: T::Hash,
1168 old_code_hash: T::Hash,
1170 },
1171
1172 Called {
1180 caller: Origin<T>,
1182 contract: T::AccountId,
1184 },
1185
1186 DelegateCalled {
1194 contract: T::AccountId,
1197 code_hash: CodeHash<T>,
1199 },
1200
1201 StorageDepositTransferredAndHeld {
1203 from: T::AccountId,
1204 to: T::AccountId,
1205 amount: BalanceOf<T>,
1206 },
1207
1208 StorageDepositTransferredAndReleased {
1210 from: T::AccountId,
1211 to: T::AccountId,
1212 amount: BalanceOf<T>,
1213 },
1214 }
1215
1216 #[pallet::error]
1217 pub enum Error<T> {
1218 InvalidSchedule,
1220 InvalidCallFlags,
1222 OutOfGas,
1224 OutputBufferTooSmall,
1226 TransferFailed,
1229 MaxCallDepthReached,
1232 ContractNotFound,
1234 CodeTooLarge,
1237 CodeNotFound,
1239 CodeInfoNotFound,
1241 OutOfBounds,
1243 DecodingFailed,
1245 ContractTrapped,
1247 ValueTooLarge,
1249 TerminatedWhileReentrant,
1252 InputForwarded,
1254 RandomSubjectTooLong,
1256 TooManyTopics,
1258 NoChainExtension,
1262 XCMDecodeFailed,
1264 DuplicateContract,
1266 TerminatedInConstructor,
1270 ReentranceDenied,
1275 StateChangeDenied,
1277 StorageDepositNotEnoughFunds,
1279 StorageDepositLimitExhausted,
1281 CodeInUse,
1283 ContractReverted,
1288 CodeRejected,
1297 Indeterministic,
1299 MigrationInProgress,
1301 NoMigrationPerformed,
1303 MaxDelegateDependenciesReached,
1305 DelegateDependencyNotFound,
1307 DelegateDependencyAlreadyExists,
1309 CannotAddSelfAsDelegateDependency,
1311 OutOfTransientStorage,
1313 }
1314
1315 #[pallet::composite_enum]
1317 pub enum HoldReason {
1318 CodeUploadDepositReserve,
1320 StorageDepositReserve,
1322 }
1323
1324 #[pallet::storage]
1326 pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeVec<T>>;
1327
1328 #[pallet::storage]
1330 pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeInfo<T>>;
1331
1332 #[pallet::storage]
1355 pub(crate) type Nonce<T: Config> = StorageValue<_, u64, ValueQuery>;
1356
1357 #[pallet::storage]
1361 pub(crate) type ContractInfoOf<T: Config> =
1362 StorageMap<_, Twox64Concat, T::AccountId, ContractInfo<T>>;
1363
1364 #[pallet::storage]
1369 pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
1370
1371 #[pallet::storage]
1374 pub(crate) type DeletionQueueCounter<T: Config> =
1375 StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
1376
1377 #[pallet::storage]
1380 pub(crate) type MigrationInProgress<T: Config> =
1381 StorageValue<_, migration::Cursor, OptionQuery>;
1382}
1383
1384#[derive(
1386 Clone, Encode, Decode, DecodeWithMemTracking, PartialEq, TypeInfo, RuntimeDebugNoBound,
1387)]
1388pub enum Origin<T: Config> {
1389 Root,
1390 Signed(T::AccountId),
1391}
1392
1393impl<T: Config> Origin<T> {
1394 pub fn from_account_id(account_id: T::AccountId) -> Self {
1396 Origin::Signed(account_id)
1397 }
1398 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
1400 match o.into() {
1401 Ok(RawOrigin::Root) => Ok(Self::Root),
1402 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
1403 _ => Err(BadOrigin.into()),
1404 }
1405 }
1406 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
1408 match self {
1409 Origin::Signed(id) => Ok(id),
1410 Origin::Root => Err(DispatchError::RootNotAllowed),
1411 }
1412 }
1413}
1414
1415struct CommonInput<'a, T: Config> {
1417 origin: Origin<T>,
1418 value: BalanceOf<T>,
1419 data: Vec<u8>,
1420 gas_limit: Weight,
1421 storage_deposit_limit: Option<BalanceOf<T>>,
1422 debug_message: Option<&'a mut DebugBufferVec<T>>,
1423}
1424
1425struct CallInput<T: Config> {
1427 dest: T::AccountId,
1428 determinism: Determinism,
1429}
1430
1431enum WasmCode<T: Config> {
1433 Wasm(WasmBlob<T>),
1434 CodeHash(CodeHash<T>),
1435}
1436
1437struct InstantiateInput<T: Config> {
1439 code: WasmCode<T>,
1440 salt: Vec<u8>,
1441}
1442
1443#[derive(
1445 Copy, Clone, PartialEq, Eq, RuntimeDebug, Decode, Encode, MaxEncodedLen, scale_info::TypeInfo,
1446)]
1447pub enum CollectEvents {
1448 UnsafeCollect,
1457 Skip,
1459}
1460
1461#[derive(
1463 Copy, Clone, PartialEq, Eq, RuntimeDebug, Decode, Encode, MaxEncodedLen, scale_info::TypeInfo,
1464)]
1465pub enum DebugInfo {
1466 UnsafeDebug,
1472 Skip,
1474}
1475
1476struct InternalOutput<T: Config, O> {
1478 gas_meter: GasMeter<T>,
1480 storage_deposit: StorageDeposit<BalanceOf<T>>,
1482 result: Result<O, ExecError>,
1484}
1485
1486environmental!(executing_contract: bool);
1488
1489trait Invokable<T: Config>: Sized {
1492 type Output;
1494
1495 fn run_guarded(self, common: CommonInput<T>) -> InternalOutput<T, Self::Output> {
1504 let gas_limit = common.gas_limit;
1505
1506 if let Err(e) = self.ensure_origin(common.origin.clone()) {
1511 return InternalOutput {
1512 gas_meter: GasMeter::new(gas_limit),
1513 storage_deposit: Default::default(),
1514 result: Err(ExecError { error: e.into(), origin: ErrorOrigin::Caller }),
1515 }
1516 }
1517
1518 executing_contract::using_once(&mut false, || {
1519 executing_contract::with(|f| {
1520 if *f {
1522 return Err(())
1523 }
1524 *f = true;
1526 Ok(())
1527 })
1528 .expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1529 .map_or_else(
1530 |_| InternalOutput {
1531 gas_meter: GasMeter::new(gas_limit),
1532 storage_deposit: Default::default(),
1533 result: Err(ExecError {
1534 error: <Error<T>>::ReentranceDenied.into(),
1535 origin: ErrorOrigin::Caller,
1536 }),
1537 },
1538 |_| self.run(common, GasMeter::new(gas_limit)),
1540 )
1541 })
1542 }
1543
1544 fn run(self, common: CommonInput<T>, gas_meter: GasMeter<T>)
1549 -> InternalOutput<T, Self::Output>;
1550
1551 fn ensure_origin(&self, origin: Origin<T>) -> Result<(), DispatchError>;
1555}
1556
1557impl<T: Config> Invokable<T> for CallInput<T> {
1558 type Output = ExecReturnValue;
1559
1560 fn run(
1561 self,
1562 common: CommonInput<T>,
1563 mut gas_meter: GasMeter<T>,
1564 ) -> InternalOutput<T, Self::Output> {
1565 let CallInput { dest, determinism } = self;
1566 let CommonInput { origin, value, data, debug_message, .. } = common;
1567 let mut storage_meter =
1568 match StorageMeter::new(&origin, common.storage_deposit_limit, common.value) {
1569 Ok(meter) => meter,
1570 Err(err) =>
1571 return InternalOutput {
1572 result: Err(err.into()),
1573 gas_meter,
1574 storage_deposit: Default::default(),
1575 },
1576 };
1577 let schedule = T::Schedule::get();
1578 let result = ExecStack::<T, WasmBlob<T>>::run_call(
1579 origin.clone(),
1580 dest.clone(),
1581 &mut gas_meter,
1582 &mut storage_meter,
1583 &schedule,
1584 value,
1585 data.clone(),
1586 debug_message,
1587 determinism,
1588 );
1589
1590 match storage_meter.try_into_deposit(&origin) {
1591 Ok(storage_deposit) => InternalOutput { gas_meter, storage_deposit, result },
1592 Err(err) => InternalOutput {
1593 gas_meter,
1594 storage_deposit: Default::default(),
1595 result: Err(err.into()),
1596 },
1597 }
1598 }
1599
1600 fn ensure_origin(&self, _origin: Origin<T>) -> Result<(), DispatchError> {
1601 Ok(())
1602 }
1603}
1604
1605impl<T: Config> Invokable<T> for InstantiateInput<T> {
1606 type Output = (AccountIdOf<T>, ExecReturnValue);
1607
1608 fn run(
1609 self,
1610 common: CommonInput<T>,
1611 mut gas_meter: GasMeter<T>,
1612 ) -> InternalOutput<T, Self::Output> {
1613 let mut storage_deposit = Default::default();
1614 let try_exec = || {
1615 let schedule = T::Schedule::get();
1616 let InstantiateInput { salt, .. } = self;
1617 let CommonInput { origin: contract_origin, .. } = common;
1618 let origin = contract_origin.account_id()?;
1619
1620 let executable = match self.code {
1621 WasmCode::Wasm(module) => module,
1622 WasmCode::CodeHash(code_hash) => WasmBlob::from_storage(code_hash, &mut gas_meter)?,
1623 };
1624
1625 let contract_origin = Origin::from_account_id(origin.clone());
1626 let mut storage_meter =
1627 StorageMeter::new(&contract_origin, common.storage_deposit_limit, common.value)?;
1628 let CommonInput { value, data, debug_message, .. } = common;
1629 let result = ExecStack::<T, WasmBlob<T>>::run_instantiate(
1630 origin.clone(),
1631 executable,
1632 &mut gas_meter,
1633 &mut storage_meter,
1634 &schedule,
1635 value,
1636 data.clone(),
1637 &salt,
1638 debug_message,
1639 );
1640
1641 storage_deposit = storage_meter.try_into_deposit(&contract_origin)?;
1642 result
1643 };
1644 InternalOutput { result: try_exec(), gas_meter, storage_deposit }
1645 }
1646
1647 fn ensure_origin(&self, origin: Origin<T>) -> Result<(), DispatchError> {
1648 match origin {
1649 Origin::Signed(_) => Ok(()),
1650 Origin::Root => Err(DispatchError::RootNotAllowed),
1651 }
1652 }
1653}
1654
1655macro_rules! ensure_no_migration_in_progress {
1656 () => {
1657 if Migration::<T>::in_progress() {
1658 return ContractResult {
1659 gas_consumed: Zero::zero(),
1660 gas_required: Zero::zero(),
1661 storage_deposit: Default::default(),
1662 debug_message: Vec::new(),
1663 result: Err(Error::<T>::MigrationInProgress.into()),
1664 events: None,
1665 }
1666 }
1667 };
1668}
1669
1670impl<T: Config> Pallet<T> {
1671 pub fn bare_call(
1684 origin: T::AccountId,
1685 dest: T::AccountId,
1686 value: BalanceOf<T>,
1687 gas_limit: Weight,
1688 storage_deposit_limit: Option<BalanceOf<T>>,
1689 data: Vec<u8>,
1690 debug: DebugInfo,
1691 collect_events: CollectEvents,
1692 determinism: Determinism,
1693 ) -> ContractExecResult<BalanceOf<T>, EventRecordOf<T>> {
1694 ensure_no_migration_in_progress!();
1695
1696 let mut debug_message = if matches!(debug, DebugInfo::UnsafeDebug) {
1697 Some(DebugBufferVec::<T>::default())
1698 } else {
1699 None
1700 };
1701 let origin = Origin::from_account_id(origin);
1702 let common = CommonInput {
1703 origin,
1704 value,
1705 data,
1706 gas_limit,
1707 storage_deposit_limit,
1708 debug_message: debug_message.as_mut(),
1709 };
1710 let output = CallInput::<T> { dest, determinism }.run_guarded(common);
1711 let events = if matches!(collect_events, CollectEvents::UnsafeCollect) {
1712 Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1713 } else {
1714 None
1715 };
1716
1717 ContractExecResult {
1718 result: output.result.map_err(|r| r.error),
1719 gas_consumed: output.gas_meter.gas_consumed(),
1720 gas_required: output.gas_meter.gas_required(),
1721 storage_deposit: output.storage_deposit,
1722 debug_message: debug_message.unwrap_or_default().to_vec(),
1723 events,
1724 }
1725 }
1726
1727 pub fn bare_instantiate(
1742 origin: T::AccountId,
1743 value: BalanceOf<T>,
1744 gas_limit: Weight,
1745 mut storage_deposit_limit: Option<BalanceOf<T>>,
1746 code: Code<CodeHash<T>>,
1747 data: Vec<u8>,
1748 salt: Vec<u8>,
1749 debug: DebugInfo,
1750 collect_events: CollectEvents,
1751 ) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>, EventRecordOf<T>> {
1752 ensure_no_migration_in_progress!();
1753
1754 let mut debug_message = if debug == DebugInfo::UnsafeDebug {
1755 Some(DebugBufferVec::<T>::default())
1756 } else {
1757 None
1758 };
1759 let events = || {
1761 if collect_events == CollectEvents::UnsafeCollect {
1762 Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1763 } else {
1764 None
1765 }
1766 };
1767
1768 let (code, upload_deposit): (WasmCode<T>, BalanceOf<T>) = match code {
1769 Code::Upload(code) => {
1770 let result = Self::try_upload_code(
1771 origin.clone(),
1772 code,
1773 storage_deposit_limit.map(Into::into),
1774 Determinism::Enforced,
1775 debug_message.as_mut(),
1776 );
1777
1778 let (module, deposit) = match result {
1779 Ok(result) => result,
1780 Err(error) =>
1781 return ContractResult {
1782 gas_consumed: Zero::zero(),
1783 gas_required: Zero::zero(),
1784 storage_deposit: Default::default(),
1785 debug_message: debug_message.unwrap_or(Default::default()).into(),
1786 result: Err(error),
1787 events: events(),
1788 },
1789 };
1790
1791 storage_deposit_limit =
1792 storage_deposit_limit.map(|l| l.saturating_sub(deposit.into()));
1793 (WasmCode::Wasm(module), deposit)
1794 },
1795 Code::Existing(hash) => (WasmCode::CodeHash(hash), Default::default()),
1796 };
1797
1798 let common = CommonInput {
1799 origin: Origin::from_account_id(origin),
1800 value,
1801 data,
1802 gas_limit,
1803 storage_deposit_limit,
1804 debug_message: debug_message.as_mut(),
1805 };
1806
1807 let output = InstantiateInput::<T> { code, salt }.run_guarded(common);
1808 ContractInstantiateResult {
1809 result: output
1810 .result
1811 .map(|(account_id, result)| InstantiateReturnValue { result, account_id })
1812 .map_err(|e| e.error),
1813 gas_consumed: output.gas_meter.gas_consumed(),
1814 gas_required: output.gas_meter.gas_required(),
1815 storage_deposit: output
1816 .storage_deposit
1817 .saturating_add(&StorageDeposit::Charge(upload_deposit)),
1818 debug_message: debug_message.unwrap_or_default().to_vec(),
1819 events: events(),
1820 }
1821 }
1822
1823 pub fn bare_upload_code(
1828 origin: T::AccountId,
1829 code: Vec<u8>,
1830 storage_deposit_limit: Option<BalanceOf<T>>,
1831 determinism: Determinism,
1832 ) -> CodeUploadResult<CodeHash<T>, BalanceOf<T>> {
1833 Migration::<T>::ensure_migrated()?;
1834 let (module, deposit) =
1835 Self::try_upload_code(origin, code, storage_deposit_limit, determinism, None)?;
1836 Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1837 }
1838
1839 fn try_upload_code(
1841 origin: T::AccountId,
1842 code: Vec<u8>,
1843 storage_deposit_limit: Option<BalanceOf<T>>,
1844 determinism: Determinism,
1845 mut debug_message: Option<&mut DebugBufferVec<T>>,
1846 ) -> Result<(WasmBlob<T>, BalanceOf<T>), DispatchError> {
1847 let schedule = T::Schedule::get();
1848 let mut module =
1849 WasmBlob::from_code(code, &schedule, origin, determinism).map_err(|(err, msg)| {
1850 debug_message.as_mut().map(|d| d.try_extend(msg.bytes()));
1851 err
1852 })?;
1853 let deposit = module.store_code()?;
1854 if let Some(storage_deposit_limit) = storage_deposit_limit {
1855 ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1856 }
1857
1858 Ok((module, deposit))
1859 }
1860
1861 pub fn get_storage(address: T::AccountId, key: Vec<u8>) -> GetStorageResult {
1863 if Migration::<T>::in_progress() {
1864 return Err(ContractAccessError::MigrationInProgress)
1865 }
1866 let contract_info =
1867 ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?;
1868
1869 let maybe_value = contract_info.read(
1870 &Key::<T>::try_from_var(key)
1871 .map_err(|_| ContractAccessError::KeyDecodingFailed)?
1872 .into(),
1873 );
1874 Ok(maybe_value)
1875 }
1876
1877 pub fn contract_address(
1882 deploying_address: &T::AccountId,
1883 code_hash: &CodeHash<T>,
1884 input_data: &[u8],
1885 salt: &[u8],
1886 ) -> T::AccountId {
1887 T::AddressGenerator::contract_address(deploying_address, code_hash, input_data, salt)
1888 }
1889
1890 pub fn code_hash(account: &AccountIdOf<T>) -> Option<CodeHash<T>> {
1892 ContractInfo::<T>::load_code_hash(account)
1893 }
1894
1895 #[cfg(feature = "runtime-benchmarks")]
1897 fn store_code_raw(
1898 code: Vec<u8>,
1899 owner: T::AccountId,
1900 ) -> frame_support::dispatch::DispatchResult {
1901 let schedule = T::Schedule::get();
1902 WasmBlob::<T>::from_code_unchecked(code, &schedule, owner)?.store_code()?;
1903 Ok(())
1904 }
1905
1906 fn deposit_event(event: Event<T>) {
1908 <frame_system::Pallet<T>>::deposit_event(<T as Config>::RuntimeEvent::from(event))
1909 }
1910
1911 fn deposit_indexed_event(topics: Vec<T::Hash>, event: Event<T>) {
1913 <frame_system::Pallet<T>>::deposit_event_indexed(
1914 &topics,
1915 <T as Config>::RuntimeEvent::from(event).into(),
1916 )
1917 }
1918
1919 fn min_balance() -> BalanceOf<T> {
1921 <T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1922 }
1923
1924 fn compat_weight_limit(gas_limit: OldWeight) -> Weight {
1929 Weight::from_parts(gas_limit, u64::from(T::MaxCodeLen::get()) * 2)
1930 }
1931}
1932
1933sp_api::decl_runtime_apis! {
1934 #[api_version(2)]
1936 pub trait ContractsApi<AccountId, Balance, BlockNumber, Hash, EventRecord> where
1937 AccountId: Codec,
1938 Balance: Codec,
1939 BlockNumber: Codec,
1940 Hash: Codec,
1941 EventRecord: Codec,
1942 {
1943 fn call(
1947 origin: AccountId,
1948 dest: AccountId,
1949 value: Balance,
1950 gas_limit: Option<Weight>,
1951 storage_deposit_limit: Option<Balance>,
1952 input_data: Vec<u8>,
1953 ) -> ContractExecResult<Balance, EventRecord>;
1954
1955 fn instantiate(
1959 origin: AccountId,
1960 value: Balance,
1961 gas_limit: Option<Weight>,
1962 storage_deposit_limit: Option<Balance>,
1963 code: Code<Hash>,
1964 data: Vec<u8>,
1965 salt: Vec<u8>,
1966 ) -> ContractInstantiateResult<AccountId, Balance, EventRecord>;
1967
1968 fn upload_code(
1972 origin: AccountId,
1973 code: Vec<u8>,
1974 storage_deposit_limit: Option<Balance>,
1975 determinism: Determinism,
1976 ) -> CodeUploadResult<Hash, Balance>;
1977
1978 fn get_storage(
1984 address: AccountId,
1985 key: Vec<u8>,
1986 ) -> GetStorageResult;
1987 }
1988}