pallet_contracts_for_drink/lib.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! # Contracts Pallet
19//!
20//! The Contracts module provides functionality for the runtime to deploy and execute WebAssembly
21//! smart-contracts.
22//!
23//! - [`Config`]
24//! - [`Call`]
25//!
26//! ## Overview
27//!
28//! This module extends accounts based on the [`frame_support::traits::fungible`] traits to have
29//! smart-contract functionality. It can be used with other modules that implement accounts based on
30//! the [`frame_support::traits::fungible`] traits. These "smart-contract accounts" have the ability
31//! to instantiate smart-contracts and make calls to other contract and non-contract accounts.
32//!
33//! The smart-contract code is stored once, and later retrievable via its hash.
34//! This means that multiple smart-contracts can be instantiated from the same hash, without
35//! replicating the code each time.
36//!
37//! When a smart-contract is called, its associated code is retrieved via the code hash and gets
38//! executed. This call can alter the storage entries of the smart-contract account, instantiate new
39//! smart-contracts, or call other smart-contracts.
40//!
41//! Finally, when an account is reaped, its associated code and storage of the smart-contract
42//! account will also be deleted.
43//!
44//! ### Weight
45//!
46//! Senders must specify a [`Weight`] limit with every call, as all instructions invoked by the
47//! smart-contract require weight. Unused weight is refunded after the call, regardless of the
48//! execution outcome.
49//!
50//! If the weight limit is reached, then all calls and state changes (including balance transfers)
51//! are only reverted at the current call's contract level. For example, if contract A calls B and B
52//! runs out of gas mid-call, then all of B's calls are reverted. Assuming correct error handling by
53//! contract A, A's other calls and state changes still persist.
54//!
55//! ### Notable Scenarios
56//!
57//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not
58//! "bubble up", and the call will only revert at the specific contract level. For example, if
59//! contract A calls contract B, and B fails, A can decide how to handle that failure, either
60//! proceeding or reverting A's changes.
61//!
62//! ## Interface
63//!
64//! ### Dispatchable functions
65//!
66//! * [`Pallet::instantiate_with_code`] - Deploys a new contract from the supplied Wasm binary,
67//! optionally transferring
68//! some balance. This instantiates a new smart contract account with the supplied code and
69//! calls its constructor to initialize the contract.
70//! * [`Pallet::instantiate`] - The same as `instantiate_with_code` but instead of uploading new
71//! code an existing `code_hash` is supplied.
72//! * [`Pallet::call`] - Makes a call to an account, optionally transferring some balance.
73//! * [`Pallet::upload_code`] - Uploads new code without instantiating a contract from it.
74//! * [`Pallet::remove_code`] - Removes the stored code and refunds the deposit to its owner. Only
75//! allowed to code owner.
76//! * [`Pallet::set_code`] - Changes the code of an existing contract. Only allowed to `Root`
77//! origin.
78//! * [`Pallet::migrate`] - Runs migration steps of current multi-block migration in priority,
79//! before [`Hooks::on_idle`][frame_support::traits::Hooks::on_idle] activates.
80//!
81//! ## Usage
82//!
83//! * [`ink!`](https://use.ink) is language that enables writing Wasm-based smart contracts in plain
84//! Rust.
85
86#![allow(rustdoc::private_intra_doc_links)]
87#![cfg_attr(not(feature = "std"), no_std)]
88#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "1024")]
89
90mod address;
91mod benchmarking;
92mod exec;
93mod gas;
94mod schedule;
95mod storage;
96mod wasm;
97
98pub mod chain_extension;
99pub mod debug;
100pub mod migration;
101pub mod weights;
102
103#[cfg(test)]
104mod tests;
105use crate::{
106 exec::{
107 AccountIdOf, ErrorOrigin, ExecError, Executable, Ext, Key, MomentOf, Stack as ExecStack,
108 },
109 gas::GasMeter,
110 storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager},
111 wasm::{CodeInfo, WasmBlob},
112};
113use codec::{Codec, Decode, Encode, HasCompact, MaxEncodedLen};
114use environmental::*;
115use frame_support::{
116 dispatch::{GetDispatchInfo, Pays, PostDispatchInfo, RawOrigin, WithPostDispatchInfo},
117 ensure,
118 error::BadOrigin,
119 traits::{
120 fungible::{Inspect, Mutate, MutateHold},
121 ConstU32, Contains, Get, Randomness, Time,
122 },
123 weights::Weight,
124 BoundedVec, DefaultNoBound, RuntimeDebugNoBound,
125};
126use frame_system::{
127 ensure_signed,
128 pallet_prelude::{BlockNumberFor, OriginFor},
129 EventRecord, Pallet as System,
130};
131use pallet_contracts_primitives::{
132 Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult,
133 ContractInstantiateResult, ContractResult, ExecReturnValue, GetStorageResult,
134 InstantiateReturnValue, StorageDeposit,
135};
136use scale_info::TypeInfo;
137use smallvec::Array;
138use sp_runtime::{
139 traits::{Convert, Dispatchable, Hash, Saturating, StaticLookup, Zero},
140 DispatchError, RuntimeDebug,
141};
142use sp_std::{fmt::Debug, prelude::*};
143
144pub use crate::{
145 address::{AddressGenerator, DefaultAddressGenerator},
146 debug::Tracing,
147 exec::Frame,
148 migration::{MigrateSequence, Migration, NoopMigration},
149 pallet::*,
150 schedule::{HostFnWeights, 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
168/// The old weight type.
169///
170/// This is a copy of the [`frame_support::weights::OldWeight`] type since the contracts pallet
171/// needs to support it indefinitely.
172type OldWeight = u64;
173
174/// Used as a sentinel value when reading and writing contract memory.
175///
176/// It is usually used to signal `None` to a contract when only a primitive is allowed
177/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
178/// sentinel because contracts are never allowed to use such a large amount of resources
179/// that this value makes sense for a memory location or length.
180const SENTINEL: u32 = u32::MAX;
181
182/// The target that is used for the log output emitted by this crate.
183///
184/// Hence you can use this target to selectively increase the log level for this crate.
185///
186/// Example: `RUST_LOG=runtime::contracts=debug my_code --dev`
187const LOG_TARGET: &str = "runtime::contracts";
188
189/// Wrapper around `PhantomData` to prevent it being filtered by `scale-info`.
190///
191/// `scale-info` filters out `PhantomData` fields because usually we are only interested
192/// in sized types. However, when trying to communicate **types** as opposed to **values**
193/// we want to have those zero sized types be included.
194#[derive(Encode, Decode, DefaultNoBound, TypeInfo)]
195#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
196pub struct EnvironmentType<T>(PhantomData<T>);
197
198/// List of all runtime configurable types that are used in the communication between
199/// `pallet-contracts` and any given contract.
200///
201/// Since those types are configurable they can vary between
202/// chains all using `pallet-contracts`. Hence we need a mechanism to communicate those types
203/// in a way that can be consumed by offchain tooling.
204///
205/// This type only exists in order to appear in the metadata where it can be read by
206/// offchain tooling.
207#[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#[frame_support::pallet]
220pub mod pallet {
221 use super::*;
222 use crate::debug::Debugger;
223 use frame_support::pallet_prelude::*;
224 use frame_system::pallet_prelude::*;
225 use sp_runtime::Perbill;
226
227 /// The current storage version.
228 pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(15);
229
230 #[pallet::pallet]
231 #[pallet::storage_version(STORAGE_VERSION)]
232 pub struct Pallet<T>(_);
233
234 #[pallet::config]
235 pub trait Config: frame_system::Config {
236 /// The time implementation used to supply timestamps to contracts through `seal_now`.
237 type Time: Time;
238
239 /// The generator used to supply randomness to contracts through `seal_random`.
240 ///
241 /// # Deprecated
242 ///
243 /// Codes using the randomness functionality cannot be uploaded. Neither can contracts
244 /// be instantiated from existing codes that use this deprecated functionality. It will
245 /// be removed eventually. Hence for new `pallet-contracts` deployments it is okay
246 /// to supply a dummy implementation for this type (because it is never used).
247 type Randomness: Randomness<Self::Hash, BlockNumberFor<Self>>;
248
249 /// The fungible in which fees are paid and contract balances are held.
250 type Currency: Inspect<Self::AccountId>
251 + Mutate<Self::AccountId>
252 + MutateHold<Self::AccountId, Reason = Self::RuntimeHoldReason>;
253
254 /// The overarching event type.
255 type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
256
257 /// The overarching call type.
258 type RuntimeCall: Dispatchable<RuntimeOrigin = Self::RuntimeOrigin, PostInfo = PostDispatchInfo>
259 + GetDispatchInfo
260 + codec::Decode
261 + IsType<<Self as frame_system::Config>::RuntimeCall>;
262
263 /// Filter that is applied to calls dispatched by contracts.
264 ///
265 /// Use this filter to control which dispatchables are callable by contracts.
266 /// This is applied in **addition** to [`frame_system::Config::BaseCallFilter`].
267 /// It is recommended to treat this as a whitelist.
268 ///
269 /// # Stability
270 ///
271 /// The runtime **must** make sure that all dispatchables that are callable by
272 /// contracts remain stable. In addition [`Self::RuntimeCall`] itself must remain stable.
273 /// This means that no existing variants are allowed to switch their positions.
274 ///
275 /// # Note
276 ///
277 /// Note that dispatchables that are called via contracts do not spawn their
278 /// own wasm instance for each call (as opposed to when called via a transaction).
279 /// Therefore please make sure to be restrictive about which dispatchables are allowed
280 /// in order to not introduce a new DoS vector like memory allocation patterns that can
281 /// be exploited to drive the runtime into a panic.
282 type CallFilter: Contains<<Self as frame_system::Config>::RuntimeCall>;
283
284 /// Used to answer contracts' queries regarding the current weight price. This is **not**
285 /// used to calculate the actual fee and is only for informational purposes.
286 type WeightPrice: Convert<Weight, BalanceOf<Self>>;
287
288 /// Describes the weights of the dispatchables of this module and is also used to
289 /// construct a default cost schedule.
290 type WeightInfo: WeightInfo;
291
292 /// Type that allows the runtime authors to add new host functions for a contract to call.
293 type ChainExtension: chain_extension::ChainExtension<Self> + Default;
294
295 /// Cost schedule and limits.
296 #[pallet::constant]
297 type Schedule: Get<Schedule<Self>>;
298
299 /// The type of the call stack determines the maximum nesting depth of contract calls.
300 ///
301 /// The allowed depth is `CallStack::size() + 1`.
302 /// Therefore a size of `0` means that a contract cannot use call or instantiate.
303 /// In other words only the origin called "root contract" is allowed to execute then.
304 ///
305 /// This setting along with [`MaxCodeLen`](#associatedtype.MaxCodeLen) directly affects
306 /// memory usage of your runtime.
307 type CallStack: Array<Item = Frame<Self>>;
308
309 /// The amount of balance a caller has to pay for each byte of storage.
310 ///
311 /// # Note
312 ///
313 /// Changing this value for an existing chain might need a storage migration.
314 #[pallet::constant]
315 type DepositPerByte: Get<BalanceOf<Self>>;
316
317 /// Fallback value to limit the storage deposit if it's not being set by the caller.
318 #[pallet::constant]
319 type DefaultDepositLimit: Get<BalanceOf<Self>>;
320
321 /// The amount of balance a caller has to pay for each storage item.
322 ///
323 /// # Note
324 ///
325 /// Changing this value for an existing chain might need a storage migration.
326 #[pallet::constant]
327 type DepositPerItem: Get<BalanceOf<Self>>;
328
329 /// The percentage of the storage deposit that should be held for using a code hash.
330 /// Instantiating a contract, or calling [`chain_extension::Ext::add_delegate_dependency`]
331 /// protects the code from being removed. In order to prevent abuse these actions are
332 /// protected with a percentage of the code deposit.
333 #[pallet::constant]
334 type CodeHashLockupDepositPercent: Get<Perbill>;
335
336 /// The address generator used to generate the addresses of contracts.
337 type AddressGenerator: AddressGenerator<Self>;
338
339 /// The maximum length of a contract code in bytes.
340 ///
341 /// The value should be chosen carefully taking into the account the overall memory limit
342 /// your runtime has, as well as the [maximum allowed callstack
343 /// depth](#associatedtype.CallStack). Look into the `integrity_test()` for some insights.
344 #[pallet::constant]
345 type MaxCodeLen: Get<u32>;
346
347 /// The maximum allowable length in bytes for storage keys.
348 #[pallet::constant]
349 type MaxStorageKeyLen: Get<u32>;
350
351 /// The maximum number of delegate_dependencies that a contract can lock with
352 /// [`chain_extension::Ext::add_delegate_dependency`].
353 #[pallet::constant]
354 type MaxDelegateDependencies: Get<u32>;
355
356 /// Make contract callable functions marked as `#[unstable]` available.
357 ///
358 /// Contracts that use `#[unstable]` functions won't be able to be uploaded unless
359 /// this is set to `true`. This is only meant for testnets and dev nodes in order to
360 /// experiment with new features.
361 ///
362 /// # Warning
363 ///
364 /// Do **not** set to `true` on productions chains.
365 #[pallet::constant]
366 type UnsafeUnstableInterface: Get<bool>;
367
368 /// The maximum length of the debug buffer in bytes.
369 #[pallet::constant]
370 type MaxDebugBufferLen: Get<u32>;
371
372 /// Overarching hold reason.
373 type RuntimeHoldReason: From<HoldReason>;
374
375 /// The sequence of migration steps that will be applied during a migration.
376 ///
377 /// # Examples
378 /// ```
379 /// use pallet_contracts::migration::{v10, v11};
380 /// # struct Runtime {};
381 /// # struct Currency {};
382 /// type Migrations = (v10::Migration<Runtime, Currency>, v11::Migration<Runtime>);
383 /// ```
384 ///
385 /// If you have a single migration step, you can use a tuple with a single element:
386 /// ```
387 /// use pallet_contracts::migration::v10;
388 /// # struct Runtime {};
389 /// # struct Currency {};
390 /// type Migrations = (v10::Migration<Runtime, Currency>,);
391 /// ```
392 type Migrations: MigrateSequence;
393
394 /// # Note
395 /// For most production chains, it's recommended to use the `()` implementation of this
396 /// trait. This implementation offers additional logging when the log target
397 /// "runtime::contracts" is set to trace.
398 type Debug: Debugger<Self>;
399
400 /// Type that bundles together all the runtime configurable interface types.
401 ///
402 /// This is not a real config. We just mention the type here as constant so that
403 /// its type appears in the metadata. Only valid value is `()`.
404 #[pallet::constant]
405 type Environment: Get<Environment<Self>>;
406 }
407
408 #[pallet::hooks]
409 impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
410 fn on_idle(_block: BlockNumberFor<T>, mut remaining_weight: Weight) -> Weight {
411 use migration::MigrateResult::*;
412
413 loop {
414 let (result, weight) = Migration::<T>::migrate(remaining_weight);
415 remaining_weight.saturating_reduce(weight);
416
417 match result {
418 // There is not enough weight to perform a migration, or make any progress, we
419 // just return the remaining weight.
420 NoMigrationPerformed | InProgress { steps_done: 0 } => return remaining_weight,
421 // Migration is still in progress, we can start the next step.
422 InProgress { .. } => continue,
423 // Either no migration is in progress, or we are done with all migrations, we
424 // can do some more other work with the remaining weight.
425 Completed | NoMigrationInProgress => break,
426 }
427 }
428
429 ContractInfo::<T>::process_deletion_queue_batch(remaining_weight)
430 .saturating_add(T::WeightInfo::on_process_deletion_queue_batch())
431 }
432
433 fn integrity_test() {
434 Migration::<T>::integrity_test();
435
436 // Total runtime memory limit
437 let max_runtime_mem: u32 = T::Schedule::get().limits.runtime_memory;
438 // Memory limits for a single contract:
439 // Value stack size: 1Mb per contract, default defined in wasmi
440 const MAX_STACK_SIZE: u32 = 1024 * 1024;
441 // Heap limit is normally 16 mempages of 64kb each = 1Mb per contract
442 let max_heap_size = T::Schedule::get().limits.max_memory_size();
443 // Max call depth is CallStack::size() + 1
444 let max_call_depth = u32::try_from(T::CallStack::size().saturating_add(1))
445 .expect("CallStack size is too big");
446
447 // Check that given configured `MaxCodeLen`, runtime heap memory limit can't be broken.
448 //
449 // In worst case, the decoded Wasm contract code would be `x16` times larger than the
450 // encoded one. This is because even a single-byte wasm instruction has 16-byte size in
451 // wasmi. This gives us `MaxCodeLen*16` safety margin.
452 //
453 // Next, the pallet keeps the Wasm blob for each
454 // contract, hence we add up `MaxCodeLen` to the safety margin.
455 //
456 // Finally, the inefficiencies of the freeing-bump allocator
457 // being used in the client for the runtime memory allocations, could lead to possible
458 // memory allocations for contract code grow up to `x4` times in some extreme cases,
459 // which gives us total multiplier of `17*4` for `MaxCodeLen`.
460 //
461 // That being said, for every contract executed in runtime, at least `MaxCodeLen*17*4`
462 // memory should be available. Note that maximum allowed heap memory and stack size per
463 // each contract (stack frame) should also be counted.
464 //
465 // Finally, we allow 50% of the runtime memory to be utilized by the contracts call
466 // stack, keeping the rest for other facilities, such as PoV, etc.
467 //
468 // This gives us the following formula:
469 //
470 // `(MaxCodeLen * 17 * 4 + MAX_STACK_SIZE + max_heap_size) * max_call_depth <
471 // max_runtime_mem/2`
472 //
473 // Hence the upper limit for the `MaxCodeLen` can be defined as follows:
474 let code_len_limit = max_runtime_mem
475 .saturating_div(2)
476 .saturating_div(max_call_depth)
477 .saturating_sub(max_heap_size)
478 .saturating_sub(MAX_STACK_SIZE)
479 .saturating_div(17 * 4);
480
481 assert!(
482 T::MaxCodeLen::get() < code_len_limit,
483 "Given `CallStack` height {:?}, `MaxCodeLen` should be set less than {:?} \
484 (current value is {:?}), to avoid possible runtime oom issues.",
485 max_call_depth,
486 code_len_limit,
487 T::MaxCodeLen::get(),
488 );
489
490 // Debug buffer should at least be large enough to accommodate a simple error message
491 const MIN_DEBUG_BUF_SIZE: u32 = 256;
492 assert!(
493 T::MaxDebugBufferLen::get() > MIN_DEBUG_BUF_SIZE,
494 "Debug buffer should have minimum size of {} (current setting is {})",
495 MIN_DEBUG_BUF_SIZE,
496 T::MaxDebugBufferLen::get(),
497 )
498 }
499 }
500
501 #[pallet::call]
502 impl<T: Config> Pallet<T>
503 where
504 <BalanceOf<T> as HasCompact>::Type: Clone + Eq + PartialEq + Debug + TypeInfo + Encode,
505 {
506 /// Deprecated version if [`Self::call`] for use in an in-storage `Call`.
507 #[pallet::call_index(0)]
508 #[pallet::weight(T::WeightInfo::call().saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit)))]
509 #[allow(deprecated)]
510 #[deprecated(note = "1D weight is used in this extrinsic, please migrate to `call`")]
511 pub fn call_old_weight(
512 origin: OriginFor<T>,
513 dest: AccountIdLookupOf<T>,
514 #[pallet::compact] value: BalanceOf<T>,
515 #[pallet::compact] gas_limit: OldWeight,
516 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
517 data: Vec<u8>,
518 ) -> DispatchResultWithPostInfo {
519 Self::call(
520 origin,
521 dest,
522 value,
523 <Pallet<T>>::compat_weight_limit(gas_limit),
524 storage_deposit_limit,
525 data,
526 )
527 }
528
529 /// Deprecated version if [`Self::instantiate_with_code`] for use in an in-storage `Call`.
530 #[pallet::call_index(1)]
531 #[pallet::weight(
532 T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
533 .saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit))
534 )]
535 #[allow(deprecated)]
536 #[deprecated(
537 note = "1D weight is used in this extrinsic, please migrate to `instantiate_with_code`"
538 )]
539 pub fn instantiate_with_code_old_weight(
540 origin: OriginFor<T>,
541 #[pallet::compact] value: BalanceOf<T>,
542 #[pallet::compact] gas_limit: OldWeight,
543 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
544 code: Vec<u8>,
545 data: Vec<u8>,
546 salt: Vec<u8>,
547 ) -> DispatchResultWithPostInfo {
548 Self::instantiate_with_code(
549 origin,
550 value,
551 <Pallet<T>>::compat_weight_limit(gas_limit),
552 storage_deposit_limit,
553 code,
554 data,
555 salt,
556 )
557 }
558
559 /// Deprecated version if [`Self::instantiate`] for use in an in-storage `Call`.
560 #[pallet::call_index(2)]
561 #[pallet::weight(
562 T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(<Pallet<T>>::compat_weight_limit(*gas_limit))
563 )]
564 #[allow(deprecated)]
565 #[deprecated(note = "1D weight is used in this extrinsic, please migrate to `instantiate`")]
566 pub fn instantiate_old_weight(
567 origin: OriginFor<T>,
568 #[pallet::compact] value: BalanceOf<T>,
569 #[pallet::compact] gas_limit: OldWeight,
570 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
571 code_hash: CodeHash<T>,
572 data: Vec<u8>,
573 salt: Vec<u8>,
574 ) -> DispatchResultWithPostInfo {
575 Self::instantiate(
576 origin,
577 value,
578 <Pallet<T>>::compat_weight_limit(gas_limit),
579 storage_deposit_limit,
580 code_hash,
581 data,
582 salt,
583 )
584 }
585
586 /// Upload new `code` without instantiating a contract from it.
587 ///
588 /// If the code does not already exist a deposit is reserved from the caller
589 /// and unreserved only when [`Self::remove_code`] is called. The size of the reserve
590 /// depends on the size of the supplied `code`.
591 ///
592 /// If the code already exists in storage it will still return `Ok` and upgrades
593 /// the in storage version to the current
594 /// [`InstructionWeights::version`](InstructionWeights).
595 ///
596 /// - `determinism`: If this is set to any other value but [`Determinism::Enforced`] then
597 /// the only way to use this code is to delegate call into it from an offchain execution.
598 /// Set to [`Determinism::Enforced`] if in doubt.
599 ///
600 /// # Note
601 ///
602 /// Anyone can instantiate a contract from any uploaded code and thus prevent its removal.
603 /// To avoid this situation a constructor could employ access control so that it can
604 /// only be instantiated by permissioned entities. The same is true when uploading
605 /// through [`Self::instantiate_with_code`].
606 #[pallet::call_index(3)]
607 #[pallet::weight(T::WeightInfo::upload_code(code.len() as u32))]
608 pub fn upload_code(
609 origin: OriginFor<T>,
610 code: Vec<u8>,
611 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
612 determinism: Determinism,
613 ) -> DispatchResult {
614 Migration::<T>::ensure_migrated()?;
615 let origin = ensure_signed(origin)?;
616 Self::bare_upload_code(origin, code, storage_deposit_limit.map(Into::into), determinism)
617 .map(|_| ())
618 }
619
620 /// Remove the code stored under `code_hash` and refund the deposit to its owner.
621 ///
622 /// A code can only be removed by its original uploader (its owner) and only if it is
623 /// not used by any contract.
624 #[pallet::call_index(4)]
625 #[pallet::weight(T::WeightInfo::remove_code())]
626 pub fn remove_code(
627 origin: OriginFor<T>,
628 code_hash: CodeHash<T>,
629 ) -> DispatchResultWithPostInfo {
630 Migration::<T>::ensure_migrated()?;
631 let origin = ensure_signed(origin)?;
632 <WasmBlob<T>>::remove(&origin, code_hash)?;
633 // we waive the fee because removing unused code is beneficial
634 Ok(Pays::No.into())
635 }
636
637 /// Privileged function that changes the code of an existing contract.
638 ///
639 /// This takes care of updating refcounts and all other necessary operations. Returns
640 /// an error if either the `code_hash` or `dest` do not exist.
641 ///
642 /// # Note
643 ///
644 /// This does **not** change the address of the contract in question. This means
645 /// that the contract address is no longer derived from its code hash after calling
646 /// this dispatchable.
647 #[pallet::call_index(5)]
648 #[pallet::weight(T::WeightInfo::set_code())]
649 pub fn set_code(
650 origin: OriginFor<T>,
651 dest: AccountIdLookupOf<T>,
652 code_hash: CodeHash<T>,
653 ) -> DispatchResult {
654 Migration::<T>::ensure_migrated()?;
655 ensure_root(origin)?;
656 let dest = T::Lookup::lookup(dest)?;
657 <ContractInfoOf<T>>::try_mutate(&dest, |contract| {
658 let contract = if let Some(contract) = contract {
659 contract
660 } else {
661 return Err(<Error<T>>::ContractNotFound.into())
662 };
663 <ExecStack<T, WasmBlob<T>>>::increment_refcount(code_hash)?;
664 <ExecStack<T, WasmBlob<T>>>::decrement_refcount(contract.code_hash);
665 Self::deposit_event(
666 vec![T::Hashing::hash_of(&dest), code_hash, contract.code_hash],
667 Event::ContractCodeUpdated {
668 contract: dest.clone(),
669 new_code_hash: code_hash,
670 old_code_hash: contract.code_hash,
671 },
672 );
673 contract.code_hash = code_hash;
674 Ok(())
675 })
676 }
677
678 /// Makes a call to an account, optionally transferring some balance.
679 ///
680 /// # Parameters
681 ///
682 /// * `dest`: Address of the contract to call.
683 /// * `value`: The balance to transfer from the `origin` to `dest`.
684 /// * `gas_limit`: The gas limit enforced when executing the constructor.
685 /// * `storage_deposit_limit`: The maximum amount of balance that can be charged from the
686 /// caller to pay for the storage consumed.
687 /// * `data`: The input data to pass to the contract.
688 ///
689 /// * If the account is a smart-contract account, the associated code will be
690 /// executed and any value will be transferred.
691 /// * If the account is a regular account, any value will be transferred.
692 /// * If no account exists and the call value is not less than `existential_deposit`,
693 /// a regular account will be created and any value will be transferred.
694 #[pallet::call_index(6)]
695 #[pallet::weight(T::WeightInfo::call().saturating_add(*gas_limit))]
696 pub fn call(
697 origin: OriginFor<T>,
698 dest: AccountIdLookupOf<T>,
699 #[pallet::compact] value: BalanceOf<T>,
700 gas_limit: Weight,
701 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
702 data: Vec<u8>,
703 ) -> DispatchResultWithPostInfo {
704 Migration::<T>::ensure_migrated()?;
705 let common = CommonInput {
706 origin: Origin::from_runtime_origin(origin)?,
707 value,
708 data,
709 gas_limit: gas_limit.into(),
710 storage_deposit_limit: storage_deposit_limit.map(Into::into),
711 debug_message: None,
712 };
713 let dest = T::Lookup::lookup(dest)?;
714 let mut output =
715 CallInput::<T> { dest, determinism: Determinism::Enforced }.run_guarded(common);
716 if let Ok(retval) = &output.result {
717 if retval.did_revert() {
718 output.result = Err(<Error<T>>::ContractReverted.into());
719 }
720 }
721 output.gas_meter.into_dispatch_result(output.result, T::WeightInfo::call())
722 }
723
724 /// Instantiates a new contract from the supplied `code` optionally transferring
725 /// some balance.
726 ///
727 /// This dispatchable has the same effect as calling [`Self::upload_code`] +
728 /// [`Self::instantiate`]. Bundling them together provides efficiency gains. Please
729 /// also check the documentation of [`Self::upload_code`].
730 ///
731 /// # Parameters
732 ///
733 /// * `value`: The balance to transfer from the `origin` to the newly created contract.
734 /// * `gas_limit`: The gas limit enforced when executing the constructor.
735 /// * `storage_deposit_limit`: The maximum amount of balance that can be charged/reserved
736 /// from the caller to pay for the storage consumed.
737 /// * `code`: The contract code to deploy in raw bytes.
738 /// * `data`: The input data to pass to the contract constructor.
739 /// * `salt`: Used for the address derivation. See [`Pallet::contract_address`].
740 ///
741 /// Instantiation is executed as follows:
742 ///
743 /// - The supplied `code` is deployed, and a `code_hash` is created for that code.
744 /// - If the `code_hash` already exists on the chain the underlying `code` will be shared.
745 /// - The destination address is computed based on the sender, code_hash and the salt.
746 /// - The smart-contract account is created at the computed address.
747 /// - The `value` is transferred to the new account.
748 /// - The `deploy` function is executed in the context of the newly-created account.
749 #[pallet::call_index(7)]
750 #[pallet::weight(
751 T::WeightInfo::instantiate_with_code(code.len() as u32, data.len() as u32, salt.len() as u32)
752 .saturating_add(*gas_limit)
753 )]
754 pub fn instantiate_with_code(
755 origin: OriginFor<T>,
756 #[pallet::compact] value: BalanceOf<T>,
757 gas_limit: Weight,
758 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
759 code: Vec<u8>,
760 data: Vec<u8>,
761 salt: Vec<u8>,
762 ) -> DispatchResultWithPostInfo {
763 Migration::<T>::ensure_migrated()?;
764 let origin = ensure_signed(origin)?;
765 let code_len = code.len() as u32;
766
767 let (module, upload_deposit) = Self::try_upload_code(
768 origin.clone(),
769 code,
770 storage_deposit_limit.clone().map(Into::into),
771 Determinism::Enforced,
772 None,
773 )?;
774
775 // Reduces the storage deposit limit by the amount that was reserved for the upload.
776 let storage_deposit_limit =
777 storage_deposit_limit.map(|limit| limit.into().saturating_sub(upload_deposit));
778
779 let data_len = data.len() as u32;
780 let salt_len = salt.len() as u32;
781 let common = CommonInput {
782 origin: Origin::from_account_id(origin),
783 value,
784 data,
785 gas_limit,
786 storage_deposit_limit,
787 debug_message: None,
788 };
789
790 let mut output =
791 InstantiateInput::<T> { code: WasmCode::Wasm(module), salt }.run_guarded(common);
792 if let Ok(retval) = &output.result {
793 if retval.1.did_revert() {
794 output.result = Err(<Error<T>>::ContractReverted.into());
795 }
796 }
797
798 output.gas_meter.into_dispatch_result(
799 output.result.map(|(_address, output)| output),
800 T::WeightInfo::instantiate_with_code(code_len, data_len, salt_len),
801 )
802 }
803
804 /// Instantiates a contract from a previously deployed wasm binary.
805 ///
806 /// This function is identical to [`Self::instantiate_with_code`] but without the
807 /// code deployment step. Instead, the `code_hash` of an on-chain deployed wasm binary
808 /// must be supplied.
809 #[pallet::call_index(8)]
810 #[pallet::weight(
811 T::WeightInfo::instantiate(data.len() as u32, salt.len() as u32).saturating_add(*gas_limit)
812 )]
813 pub fn instantiate(
814 origin: OriginFor<T>,
815 #[pallet::compact] value: BalanceOf<T>,
816 gas_limit: Weight,
817 storage_deposit_limit: Option<<BalanceOf<T> as codec::HasCompact>::Type>,
818 code_hash: CodeHash<T>,
819 data: Vec<u8>,
820 salt: Vec<u8>,
821 ) -> DispatchResultWithPostInfo {
822 Migration::<T>::ensure_migrated()?;
823 let data_len = data.len() as u32;
824 let salt_len = salt.len() as u32;
825 let common = CommonInput {
826 origin: Origin::from_runtime_origin(origin)?,
827 value,
828 data,
829 gas_limit,
830 storage_deposit_limit: storage_deposit_limit.map(Into::into),
831 debug_message: None,
832 };
833 let mut output = InstantiateInput::<T> { code: WasmCode::CodeHash(code_hash), salt }
834 .run_guarded(common);
835 if let Ok(retval) = &output.result {
836 if retval.1.did_revert() {
837 output.result = Err(<Error<T>>::ContractReverted.into());
838 }
839 }
840 output.gas_meter.into_dispatch_result(
841 output.result.map(|(_address, output)| output),
842 T::WeightInfo::instantiate(data_len, salt_len),
843 )
844 }
845
846 /// When a migration is in progress, this dispatchable can be used to run migration steps.
847 /// Calls that contribute to advancing the migration have their fees waived, as it's helpful
848 /// for the chain. Note that while the migration is in progress, the pallet will also
849 /// leverage the `on_idle` hooks to run migration steps.
850 #[pallet::call_index(9)]
851 #[pallet::weight(T::WeightInfo::migrate().saturating_add(*weight_limit))]
852 pub fn migrate(origin: OriginFor<T>, weight_limit: Weight) -> DispatchResultWithPostInfo {
853 use migration::MigrateResult::*;
854 ensure_signed(origin)?;
855
856 let weight_limit = weight_limit.saturating_add(T::WeightInfo::migrate());
857 let (result, weight) = Migration::<T>::migrate(weight_limit);
858
859 match result {
860 Completed =>
861 Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::No }),
862 InProgress { steps_done, .. } if steps_done > 0 =>
863 Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::No }),
864 InProgress { .. } =>
865 Ok(PostDispatchInfo { actual_weight: Some(weight), pays_fee: Pays::Yes }),
866 NoMigrationInProgress | NoMigrationPerformed => {
867 let err: DispatchError = <Error<T>>::NoMigrationPerformed.into();
868 Err(err.with_weight(T::WeightInfo::migrate()))
869 },
870 }
871 }
872 }
873
874 #[pallet::event]
875 pub enum Event<T: Config> {
876 /// Contract deployed by address at the specified address.
877 Instantiated { deployer: T::AccountId, contract: T::AccountId },
878
879 /// Contract has been removed.
880 ///
881 /// # Note
882 ///
883 /// The only way for a contract to be removed and emitting this event is by calling
884 /// `seal_terminate`.
885 Terminated {
886 /// The contract that was terminated.
887 contract: T::AccountId,
888 /// The account that received the contracts remaining balance
889 beneficiary: T::AccountId,
890 },
891
892 /// Code with the specified hash has been stored.
893 CodeStored { code_hash: T::Hash, deposit_held: BalanceOf<T>, uploader: T::AccountId },
894
895 /// A custom event emitted by the contract.
896 ContractEmitted {
897 /// The contract that emitted the event.
898 contract: T::AccountId,
899 /// Data supplied by the contract. Metadata generated during contract compilation
900 /// is needed to decode it.
901 data: Vec<u8>,
902 },
903
904 /// A code with the specified hash was removed.
905 CodeRemoved { code_hash: T::Hash, deposit_released: BalanceOf<T>, remover: T::AccountId },
906
907 /// A contract's code was updated.
908 ContractCodeUpdated {
909 /// The contract that has been updated.
910 contract: T::AccountId,
911 /// New code hash that was set for the contract.
912 new_code_hash: T::Hash,
913 /// Previous code hash of the contract.
914 old_code_hash: T::Hash,
915 },
916
917 /// A contract was called either by a plain account or another contract.
918 ///
919 /// # Note
920 ///
921 /// Please keep in mind that like all events this is only emitted for successful
922 /// calls. This is because on failure all storage changes including events are
923 /// rolled back.
924 Called {
925 /// The caller of the `contract`.
926 caller: Origin<T>,
927 /// The contract that was called.
928 contract: T::AccountId,
929 },
930
931 /// A contract delegate called a code hash.
932 ///
933 /// # Note
934 ///
935 /// Please keep in mind that like all events this is only emitted for successful
936 /// calls. This is because on failure all storage changes including events are
937 /// rolled back.
938 DelegateCalled {
939 /// The contract that performed the delegate call and hence in whose context
940 /// the `code_hash` is executed.
941 contract: T::AccountId,
942 /// The code hash that was delegate called.
943 code_hash: CodeHash<T>,
944 },
945
946 /// Some funds have been transferred and held as storage deposit.
947 StorageDepositTransferredAndHeld {
948 from: T::AccountId,
949 to: T::AccountId,
950 amount: BalanceOf<T>,
951 },
952
953 /// Some storage deposit funds have been transferred and released.
954 StorageDepositTransferredAndReleased {
955 from: T::AccountId,
956 to: T::AccountId,
957 amount: BalanceOf<T>,
958 },
959 }
960
961 #[pallet::error]
962 pub enum Error<T> {
963 /// Invalid schedule supplied, e.g. with zero weight of a basic operation.
964 InvalidSchedule,
965 /// Invalid combination of flags supplied to `seal_call` or `seal_delegate_call`.
966 InvalidCallFlags,
967 /// The executed contract exhausted its gas limit.
968 OutOfGas,
969 /// The output buffer supplied to a contract API call was too small.
970 OutputBufferTooSmall,
971 /// Performing the requested transfer failed. Probably because there isn't enough
972 /// free balance in the sender's account.
973 TransferFailed,
974 /// Performing a call was denied because the calling depth reached the limit
975 /// of what is specified in the schedule.
976 MaxCallDepthReached,
977 /// No contract was found at the specified address.
978 ContractNotFound,
979 /// The code supplied to `instantiate_with_code` exceeds the limit specified in the
980 /// current schedule.
981 CodeTooLarge,
982 /// No code could be found at the supplied code hash.
983 CodeNotFound,
984 /// No code info could be found at the supplied code hash.
985 CodeInfoNotFound,
986 /// A buffer outside of sandbox memory was passed to a contract API function.
987 OutOfBounds,
988 /// Input passed to a contract API function failed to decode as expected type.
989 DecodingFailed,
990 /// Contract trapped during execution.
991 ContractTrapped,
992 /// The size defined in `T::MaxValueSize` was exceeded.
993 ValueTooLarge,
994 /// Termination of a contract is not allowed while the contract is already
995 /// on the call stack. Can be triggered by `seal_terminate`.
996 TerminatedWhileReentrant,
997 /// `seal_call` forwarded this contracts input. It therefore is no longer available.
998 InputForwarded,
999 /// The subject passed to `seal_random` exceeds the limit.
1000 RandomSubjectTooLong,
1001 /// The amount of topics passed to `seal_deposit_events` exceeds the limit.
1002 TooManyTopics,
1003 /// The chain does not provide a chain extension. Calling the chain extension results
1004 /// in this error. Note that this usually shouldn't happen as deploying such contracts
1005 /// is rejected.
1006 NoChainExtension,
1007 /// A contract with the same AccountId already exists.
1008 DuplicateContract,
1009 /// A contract self destructed in its constructor.
1010 ///
1011 /// This can be triggered by a call to `seal_terminate`.
1012 TerminatedInConstructor,
1013 /// A call tried to invoke a contract that is flagged as non-reentrant.
1014 /// The only other cause is that a call from a contract into the runtime tried to call back
1015 /// into `pallet-contracts`. This would make the whole pallet reentrant with regard to
1016 /// contract code execution which is not supported.
1017 ReentranceDenied,
1018 /// Origin doesn't have enough balance to pay the required storage deposits.
1019 StorageDepositNotEnoughFunds,
1020 /// More storage was created than allowed by the storage deposit limit.
1021 StorageDepositLimitExhausted,
1022 /// Code removal was denied because the code is still in use by at least one contract.
1023 CodeInUse,
1024 /// The contract ran to completion but decided to revert its storage changes.
1025 /// Please note that this error is only returned from extrinsics. When called directly
1026 /// or via RPC an `Ok` will be returned. In this case the caller needs to inspect the flags
1027 /// to determine whether a reversion has taken place.
1028 ContractReverted,
1029 /// The contract's code was found to be invalid during validation.
1030 ///
1031 /// The most likely cause of this is that an API was used which is not supported by the
1032 /// node. This happens if an older node is used with a new version of ink!. Try updating
1033 /// your node to the newest available version.
1034 ///
1035 /// A more detailed error can be found on the node console if debug messages are enabled
1036 /// by supplying `-lruntime::contracts=debug`.
1037 CodeRejected,
1038 /// An indetermistic code was used in a context where this is not permitted.
1039 Indeterministic,
1040 /// A pending migration needs to complete before the extrinsic can be called.
1041 MigrationInProgress,
1042 /// Migrate dispatch call was attempted but no migration was performed.
1043 NoMigrationPerformed,
1044 /// The contract has reached its maximum number of delegate dependencies.
1045 MaxDelegateDependenciesReached,
1046 /// The dependency was not found in the contract's delegate dependencies.
1047 DelegateDependencyNotFound,
1048 /// The contract already depends on the given delegate dependency.
1049 DelegateDependencyAlreadyExists,
1050 /// Can not add a delegate dependency to the code hash of the contract itself.
1051 CannotAddSelfAsDelegateDependency,
1052 }
1053
1054 /// A reason for the pallet contracts placing a hold on funds.
1055 #[pallet::composite_enum]
1056 pub enum HoldReason {
1057 /// The Pallet has reserved it for storing code on-chain.
1058 CodeUploadDepositReserve,
1059 /// The Pallet has reserved it for storage deposit.
1060 StorageDepositReserve,
1061 }
1062
1063 /// A mapping from a contract's code hash to its code.
1064 #[pallet::storage]
1065 pub(crate) type PristineCode<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeVec<T>>;
1066
1067 /// A mapping from a contract's code hash to its code info.
1068 #[pallet::storage]
1069 pub(crate) type CodeInfoOf<T: Config> = StorageMap<_, Identity, CodeHash<T>, CodeInfo<T>>;
1070
1071 /// This is a **monotonic** counter incremented on contract instantiation.
1072 ///
1073 /// This is used in order to generate unique trie ids for contracts.
1074 /// The trie id of a new contract is calculated from hash(account_id, nonce).
1075 /// The nonce is required because otherwise the following sequence would lead to
1076 /// a possible collision of storage:
1077 ///
1078 /// 1. Create a new contract.
1079 /// 2. Terminate the contract.
1080 /// 3. Immediately recreate the contract with the same account_id.
1081 ///
1082 /// This is bad because the contents of a trie are deleted lazily and there might be
1083 /// storage of the old instantiation still in it when the new contract is created. Please
1084 /// note that we can't replace the counter by the block number because the sequence above
1085 /// can happen in the same block. We also can't keep the account counter in memory only
1086 /// because storage is the only way to communicate across different extrinsics in the
1087 /// same block.
1088 ///
1089 /// # Note
1090 ///
1091 /// Do not use it to determine the number of contracts. It won't be decremented if
1092 /// a contract is destroyed.
1093 #[pallet::storage]
1094 pub(crate) type Nonce<T: Config> = StorageValue<_, u64, ValueQuery>;
1095
1096 /// The code associated with a given account.
1097 ///
1098 /// TWOX-NOTE: SAFE since `AccountId` is a secure hash.
1099 #[pallet::storage]
1100 pub(crate) type ContractInfoOf<T: Config> =
1101 StorageMap<_, Twox64Concat, T::AccountId, ContractInfo<T>>;
1102
1103 /// Evicted contracts that await child trie deletion.
1104 ///
1105 /// Child trie deletion is a heavy operation depending on the amount of storage items
1106 /// stored in said trie. Therefore this operation is performed lazily in `on_idle`.
1107 #[pallet::storage]
1108 pub(crate) type DeletionQueue<T: Config> = StorageMap<_, Twox64Concat, u32, TrieId>;
1109
1110 /// A pair of monotonic counters used to track the latest contract marked for deletion
1111 /// and the latest deleted contract in queue.
1112 #[pallet::storage]
1113 pub(crate) type DeletionQueueCounter<T: Config> =
1114 StorageValue<_, DeletionQueueManager<T>, ValueQuery>;
1115
1116 /// A migration can span across multiple blocks. This storage defines a cursor to track the
1117 /// progress of the migration, enabling us to resume from the last completed position.
1118 #[pallet::storage]
1119 pub(crate) type MigrationInProgress<T: Config> =
1120 StorageValue<_, migration::Cursor, OptionQuery>;
1121}
1122
1123/// The type of origins supported by the contracts pallet.
1124#[derive(Clone, Encode, Decode, PartialEq, TypeInfo, RuntimeDebugNoBound)]
1125pub enum Origin<T: Config> {
1126 Root,
1127 Signed(T::AccountId),
1128}
1129
1130impl<T: Config> Origin<T> {
1131 /// Creates a new Signed Caller from an AccountId.
1132 pub fn from_account_id(account_id: T::AccountId) -> Self {
1133 Origin::Signed(account_id)
1134 }
1135 /// Creates a new Origin from a `RuntimeOrigin`.
1136 pub fn from_runtime_origin(o: OriginFor<T>) -> Result<Self, DispatchError> {
1137 match o.into() {
1138 Ok(RawOrigin::Root) => Ok(Self::Root),
1139 Ok(RawOrigin::Signed(t)) => Ok(Self::Signed(t)),
1140 _ => Err(BadOrigin.into()),
1141 }
1142 }
1143 /// Returns the AccountId of a Signed Origin or an error if the origin is Root.
1144 pub fn account_id(&self) -> Result<&T::AccountId, DispatchError> {
1145 match self {
1146 Origin::Signed(id) => Ok(id),
1147 Origin::Root => Err(DispatchError::RootNotAllowed),
1148 }
1149 }
1150}
1151
1152/// Context of a contract invocation.
1153struct CommonInput<'a, T: Config> {
1154 origin: Origin<T>,
1155 value: BalanceOf<T>,
1156 data: Vec<u8>,
1157 gas_limit: Weight,
1158 storage_deposit_limit: Option<BalanceOf<T>>,
1159 debug_message: Option<&'a mut DebugBufferVec<T>>,
1160}
1161
1162/// Input specific to a call into contract.
1163struct CallInput<T: Config> {
1164 dest: T::AccountId,
1165 determinism: Determinism,
1166}
1167
1168/// Reference to an existing code hash or a new wasm module.
1169enum WasmCode<T: Config> {
1170 Wasm(WasmBlob<T>),
1171 CodeHash(CodeHash<T>),
1172}
1173
1174/// Input specific to a contract instantiation invocation.
1175struct InstantiateInput<T: Config> {
1176 code: WasmCode<T>,
1177 salt: Vec<u8>,
1178}
1179
1180/// Determines whether events should be collected during execution.
1181#[derive(
1182 Copy, Clone, PartialEq, Eq, RuntimeDebug, Decode, Encode, MaxEncodedLen, scale_info::TypeInfo,
1183)]
1184pub enum CollectEvents {
1185 /// Collect events.
1186 ///
1187 /// # Note
1188 ///
1189 /// Events should only be collected when called off-chain, as this would otherwise
1190 /// collect all the Events emitted in the block so far and put them into the PoV.
1191 ///
1192 /// **Never** use this mode for on-chain execution.
1193 UnsafeCollect,
1194 /// Skip event collection.
1195 Skip,
1196}
1197
1198/// Determines whether debug messages will be collected.
1199#[derive(
1200 Copy, Clone, PartialEq, Eq, RuntimeDebug, Decode, Encode, MaxEncodedLen, scale_info::TypeInfo,
1201)]
1202pub enum DebugInfo {
1203 /// Collect debug messages.
1204 /// # Note
1205 ///
1206 /// This should only ever be set to `UnsafeDebug` when executing as an RPC because
1207 /// it adds allocations and could be abused to drive the runtime into an OOM panic.
1208 UnsafeDebug,
1209 /// Skip collection of debug messages.
1210 Skip,
1211}
1212
1213/// Return type of private helper functions.
1214struct InternalOutput<T: Config, O> {
1215 /// The gas meter that was used to execute the call.
1216 gas_meter: GasMeter<T>,
1217 /// The storage deposit used by the call.
1218 storage_deposit: StorageDeposit<BalanceOf<T>>,
1219 /// The result of the call.
1220 result: Result<O, ExecError>,
1221}
1222
1223/// Helper trait to wrap contract execution entry points into a single function
1224/// [`Invokable::run_guarded`].
1225trait Invokable<T: Config>: Sized {
1226 /// What is returned as a result of a successful invocation.
1227 type Output;
1228
1229 /// Single entry point to contract execution.
1230 /// Downstream execution flow is branched by implementations of [`Invokable`] trait:
1231 ///
1232 /// - [`InstantiateInput::run`] runs contract instantiation,
1233 /// - [`CallInput::run`] runs contract call.
1234 ///
1235 /// We enforce a re-entrancy guard here by initializing and checking a boolean flag through a
1236 /// global reference.
1237 fn run_guarded(self, common: CommonInput<T>) -> InternalOutput<T, Self::Output> {
1238 // Set up a global reference to the boolean flag used for the re-entrancy guard.
1239 environmental!(executing_contract: bool);
1240
1241 let gas_limit = common.gas_limit;
1242
1243 // Check whether the origin is allowed here. The logic of the access rules
1244 // is in the `ensure_origin`, this could vary for different implementations of this
1245 // trait. For example, some actions might not allow Root origin as they could require an
1246 // AccountId associated with the origin.
1247 if let Err(e) = self.ensure_origin(common.origin.clone()) {
1248 return InternalOutput {
1249 gas_meter: GasMeter::new(gas_limit),
1250 storage_deposit: Default::default(),
1251 result: Err(ExecError { error: e.into(), origin: ErrorOrigin::Caller }),
1252 }
1253 }
1254
1255 executing_contract::using_once(&mut false, || {
1256 executing_contract::with(|f| {
1257 // Fail if already entered contract execution
1258 if *f {
1259 return Err(())
1260 }
1261 // We are entering contract execution
1262 *f = true;
1263 Ok(())
1264 })
1265 .expect("Returns `Ok` if called within `using_once`. It is syntactically obvious that this is the case; qed")
1266 .map_or_else(
1267 |_| InternalOutput {
1268 gas_meter: GasMeter::new(gas_limit),
1269 storage_deposit: Default::default(),
1270 result: Err(ExecError {
1271 error: <Error<T>>::ReentranceDenied.into(),
1272 origin: ErrorOrigin::Caller,
1273 }),
1274 },
1275 // Enter contract call.
1276 |_| self.run(common, GasMeter::new(gas_limit)),
1277 )
1278 })
1279 }
1280
1281 /// Method that does the actual call to a contract. It can be either a call to a deployed
1282 /// contract or a instantiation of a new one.
1283 ///
1284 /// Called by dispatchables and public functions through the [`Invokable::run_guarded`].
1285 fn run(self, common: CommonInput<T>, gas_meter: GasMeter<T>)
1286 -> InternalOutput<T, Self::Output>;
1287
1288 /// This method ensures that the given `origin` is allowed to invoke the current `Invokable`.
1289 ///
1290 /// Called by dispatchables and public functions through the [`Invokable::run_guarded`].
1291 fn ensure_origin(&self, origin: Origin<T>) -> Result<(), DispatchError>;
1292}
1293
1294impl<T: Config> Invokable<T> for CallInput<T> {
1295 type Output = ExecReturnValue;
1296
1297 fn run(
1298 self,
1299 common: CommonInput<T>,
1300 mut gas_meter: GasMeter<T>,
1301 ) -> InternalOutput<T, Self::Output> {
1302 let CallInput { dest, determinism } = self;
1303 let CommonInput { origin, value, data, debug_message, .. } = common;
1304 let mut storage_meter =
1305 match StorageMeter::new(&origin, common.storage_deposit_limit, common.value) {
1306 Ok(meter) => meter,
1307 Err(err) =>
1308 return InternalOutput {
1309 result: Err(err.into()),
1310 gas_meter,
1311 storage_deposit: Default::default(),
1312 },
1313 };
1314 let schedule = T::Schedule::get();
1315 let result = ExecStack::<T, WasmBlob<T>>::run_call(
1316 origin.clone(),
1317 dest.clone(),
1318 &mut gas_meter,
1319 &mut storage_meter,
1320 &schedule,
1321 value,
1322 data.clone(),
1323 debug_message,
1324 determinism,
1325 );
1326
1327 match storage_meter.try_into_deposit(&origin) {
1328 Ok(storage_deposit) => InternalOutput { gas_meter, storage_deposit, result },
1329 Err(err) => InternalOutput {
1330 gas_meter,
1331 storage_deposit: Default::default(),
1332 result: Err(err.into()),
1333 },
1334 }
1335 }
1336
1337 fn ensure_origin(&self, _origin: Origin<T>) -> Result<(), DispatchError> {
1338 Ok(())
1339 }
1340}
1341
1342impl<T: Config> Invokable<T> for InstantiateInput<T> {
1343 type Output = (AccountIdOf<T>, ExecReturnValue);
1344
1345 fn run(
1346 self,
1347 common: CommonInput<T>,
1348 mut gas_meter: GasMeter<T>,
1349 ) -> InternalOutput<T, Self::Output> {
1350 let mut storage_deposit = Default::default();
1351 let try_exec = || {
1352 let schedule = T::Schedule::get();
1353 let InstantiateInput { salt, .. } = self;
1354 let CommonInput { origin: contract_origin, .. } = common;
1355 let origin = contract_origin.account_id()?;
1356
1357 let executable = match self.code {
1358 WasmCode::Wasm(module) => module,
1359 WasmCode::CodeHash(code_hash) => WasmBlob::from_storage(code_hash, &mut gas_meter)?,
1360 };
1361
1362 let contract_origin = Origin::from_account_id(origin.clone());
1363 let mut storage_meter =
1364 StorageMeter::new(&contract_origin, common.storage_deposit_limit, common.value)?;
1365 let CommonInput { value, data, debug_message, .. } = common;
1366 let result = ExecStack::<T, WasmBlob<T>>::run_instantiate(
1367 origin.clone(),
1368 executable,
1369 &mut gas_meter,
1370 &mut storage_meter,
1371 &schedule,
1372 value,
1373 data.clone(),
1374 &salt,
1375 debug_message,
1376 );
1377
1378 storage_deposit = storage_meter.try_into_deposit(&contract_origin)?;
1379 result
1380 };
1381 InternalOutput { result: try_exec(), gas_meter, storage_deposit }
1382 }
1383
1384 fn ensure_origin(&self, origin: Origin<T>) -> Result<(), DispatchError> {
1385 match origin {
1386 Origin::Signed(_) => Ok(()),
1387 Origin::Root => Err(DispatchError::RootNotAllowed),
1388 }
1389 }
1390}
1391
1392macro_rules! ensure_no_migration_in_progress {
1393 () => {
1394 if Migration::<T>::in_progress() {
1395 return ContractResult {
1396 gas_consumed: Zero::zero(),
1397 gas_required: Zero::zero(),
1398 storage_deposit: Default::default(),
1399 debug_message: Vec::new(),
1400 result: Err(Error::<T>::MigrationInProgress.into()),
1401 events: None,
1402 }
1403 }
1404 };
1405}
1406
1407impl<T: Config> Pallet<T> {
1408 /// Perform a call to a specified contract.
1409 ///
1410 /// This function is similar to [`Self::call`], but doesn't perform any address lookups
1411 /// and better suitable for calling directly from Rust.
1412 ///
1413 /// # Note
1414 ///
1415 /// If `debug` is set to `DebugInfo::UnsafeDebug` it returns additional human readable debugging
1416 /// information.
1417 ///
1418 /// If `collect_events` is set to `CollectEvents::UnsafeCollect` it collects all the Events
1419 /// emitted in the block so far and the ones emitted during the execution of this contract.
1420 pub fn bare_call(
1421 origin: T::AccountId,
1422 dest: T::AccountId,
1423 value: BalanceOf<T>,
1424 gas_limit: Weight,
1425 storage_deposit_limit: Option<BalanceOf<T>>,
1426 data: Vec<u8>,
1427 debug: DebugInfo,
1428 collect_events: CollectEvents,
1429 determinism: Determinism,
1430 ) -> ContractExecResult<BalanceOf<T>, EventRecordOf<T>> {
1431 ensure_no_migration_in_progress!();
1432
1433 let mut debug_message = if matches!(debug, DebugInfo::UnsafeDebug) {
1434 Some(DebugBufferVec::<T>::default())
1435 } else {
1436 None
1437 };
1438 let origin = Origin::from_account_id(origin);
1439 let common = CommonInput {
1440 origin,
1441 value,
1442 data,
1443 gas_limit,
1444 storage_deposit_limit,
1445 debug_message: debug_message.as_mut(),
1446 };
1447 let output = CallInput::<T> { dest, determinism }.run_guarded(common);
1448 let events = if matches!(collect_events, CollectEvents::UnsafeCollect) {
1449 Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1450 } else {
1451 None
1452 };
1453
1454 ContractExecResult {
1455 result: output.result.map_err(|r| r.error),
1456 gas_consumed: output.gas_meter.gas_consumed(),
1457 gas_required: output.gas_meter.gas_required(),
1458 storage_deposit: output.storage_deposit,
1459 debug_message: debug_message.unwrap_or_default().to_vec(),
1460 events,
1461 }
1462 }
1463
1464 /// Instantiate a new contract.
1465 ///
1466 /// This function is similar to [`Self::instantiate`], but doesn't perform any address lookups
1467 /// and better suitable for calling directly from Rust.
1468 ///
1469 /// It returns the execution result, account id and the amount of used weight.
1470 ///
1471 /// # Note
1472 ///
1473 /// If `debug` is set to `DebugInfo::UnsafeDebug` it returns additional human readable debugging
1474 /// information.
1475 ///
1476 /// If `collect_events` is set to `CollectEvents::UnsafeCollect` it collects all the Events
1477 /// emitted in the block so far.
1478 pub fn bare_instantiate(
1479 origin: T::AccountId,
1480 value: BalanceOf<T>,
1481 gas_limit: Weight,
1482 mut storage_deposit_limit: Option<BalanceOf<T>>,
1483 code: Code<CodeHash<T>>,
1484 data: Vec<u8>,
1485 salt: Vec<u8>,
1486 debug: DebugInfo,
1487 collect_events: CollectEvents,
1488 ) -> ContractInstantiateResult<T::AccountId, BalanceOf<T>, EventRecordOf<T>> {
1489 ensure_no_migration_in_progress!();
1490
1491 let mut debug_message = if debug == DebugInfo::UnsafeDebug {
1492 Some(DebugBufferVec::<T>::default())
1493 } else {
1494 None
1495 };
1496 // collect events if CollectEvents is UnsafeCollect
1497 let events = || {
1498 if collect_events == CollectEvents::UnsafeCollect {
1499 Some(System::<T>::read_events_no_consensus().map(|e| *e).collect())
1500 } else {
1501 None
1502 }
1503 };
1504
1505 let (code, upload_deposit): (WasmCode<T>, BalanceOf<T>) = match code {
1506 Code::Upload(code) => {
1507 let result = Self::try_upload_code(
1508 origin.clone(),
1509 code,
1510 storage_deposit_limit.map(Into::into),
1511 Determinism::Enforced,
1512 debug_message.as_mut(),
1513 );
1514
1515 let (module, deposit) = match result {
1516 Ok(result) => result,
1517 Err(error) =>
1518 return ContractResult {
1519 gas_consumed: Zero::zero(),
1520 gas_required: Zero::zero(),
1521 storage_deposit: Default::default(),
1522 debug_message: debug_message.unwrap_or(Default::default()).into(),
1523 result: Err(error),
1524 events: events(),
1525 },
1526 };
1527
1528 storage_deposit_limit =
1529 storage_deposit_limit.map(|l| l.saturating_sub(deposit.into()));
1530 (WasmCode::Wasm(module), deposit)
1531 },
1532 Code::Existing(hash) => (WasmCode::CodeHash(hash), Default::default()),
1533 };
1534
1535 let common = CommonInput {
1536 origin: Origin::from_account_id(origin),
1537 value,
1538 data,
1539 gas_limit,
1540 storage_deposit_limit,
1541 debug_message: debug_message.as_mut(),
1542 };
1543
1544 let output = InstantiateInput::<T> { code, salt }.run_guarded(common);
1545 ContractInstantiateResult {
1546 result: output
1547 .result
1548 .map(|(account_id, result)| InstantiateReturnValue { result, account_id })
1549 .map_err(|e| e.error),
1550 gas_consumed: output.gas_meter.gas_consumed(),
1551 gas_required: output.gas_meter.gas_required(),
1552 storage_deposit: output
1553 .storage_deposit
1554 .saturating_add(&StorageDeposit::Charge(upload_deposit)),
1555 debug_message: debug_message.unwrap_or_default().to_vec(),
1556 events: events(),
1557 }
1558 }
1559
1560 /// Upload new code without instantiating a contract from it.
1561 ///
1562 /// This function is similar to [`Self::upload_code`], but doesn't perform any address lookups
1563 /// and better suitable for calling directly from Rust.
1564 pub fn bare_upload_code(
1565 origin: T::AccountId,
1566 code: Vec<u8>,
1567 storage_deposit_limit: Option<BalanceOf<T>>,
1568 determinism: Determinism,
1569 ) -> CodeUploadResult<CodeHash<T>, BalanceOf<T>> {
1570 Migration::<T>::ensure_migrated()?;
1571 let (module, deposit) =
1572 Self::try_upload_code(origin, code, storage_deposit_limit, determinism, None)?;
1573 Ok(CodeUploadReturnValue { code_hash: *module.code_hash(), deposit })
1574 }
1575
1576 /// Uploads new code and returns the Wasm blob and deposit amount collected.
1577 fn try_upload_code(
1578 origin: T::AccountId,
1579 code: Vec<u8>,
1580 storage_deposit_limit: Option<BalanceOf<T>>,
1581 determinism: Determinism,
1582 mut debug_message: Option<&mut DebugBufferVec<T>>,
1583 ) -> Result<(WasmBlob<T>, BalanceOf<T>), DispatchError> {
1584 let schedule = T::Schedule::get();
1585 let mut module =
1586 WasmBlob::from_code(code, &schedule, origin, determinism).map_err(|(err, msg)| {
1587 debug_message.as_mut().map(|d| d.try_extend(msg.bytes()));
1588 err
1589 })?;
1590 let deposit = module.store_code()?;
1591 if let Some(storage_deposit_limit) = storage_deposit_limit {
1592 ensure!(storage_deposit_limit >= deposit, <Error<T>>::StorageDepositLimitExhausted);
1593 }
1594
1595 Ok((module, deposit))
1596 }
1597
1598 /// Query storage of a specified contract under a specified key.
1599 pub fn get_storage(address: T::AccountId, key: Vec<u8>) -> GetStorageResult {
1600 if Migration::<T>::in_progress() {
1601 return Err(ContractAccessError::MigrationInProgress)
1602 }
1603 let contract_info =
1604 ContractInfoOf::<T>::get(&address).ok_or(ContractAccessError::DoesntExist)?;
1605
1606 let maybe_value = contract_info.read(
1607 &Key::<T>::try_from_var(key)
1608 .map_err(|_| ContractAccessError::KeyDecodingFailed)?
1609 .into(),
1610 );
1611 Ok(maybe_value)
1612 }
1613
1614 /// Determine the address of a contract.
1615 ///
1616 /// This is the address generation function used by contract instantiation. See
1617 /// [`DefaultAddressGenerator`] for the default implementation.
1618 pub fn contract_address(
1619 deploying_address: &T::AccountId,
1620 code_hash: &CodeHash<T>,
1621 input_data: &[u8],
1622 salt: &[u8],
1623 ) -> T::AccountId {
1624 T::AddressGenerator::contract_address(deploying_address, code_hash, input_data, salt)
1625 }
1626
1627 /// Returns the code hash of the contract specified by `account` ID.
1628 pub fn code_hash(account: &AccountIdOf<T>) -> Option<CodeHash<T>> {
1629 ContractInfo::<T>::load_code_hash(account)
1630 }
1631
1632 /// Store code for benchmarks which does not validate the code.
1633 #[cfg(feature = "runtime-benchmarks")]
1634 fn store_code_raw(
1635 code: Vec<u8>,
1636 owner: T::AccountId,
1637 ) -> frame_support::dispatch::DispatchResult {
1638 let schedule = T::Schedule::get();
1639 WasmBlob::<T>::from_code_unchecked(code, &schedule, owner)?.store_code()?;
1640 Ok(())
1641 }
1642
1643 /// Deposit a pallet contracts event. Handles the conversion to the overarching event type.
1644 fn deposit_event(topics: Vec<T::Hash>, event: Event<T>) {
1645 <frame_system::Pallet<T>>::deposit_event_indexed(
1646 &topics,
1647 <T as Config>::RuntimeEvent::from(event).into(),
1648 )
1649 }
1650
1651 /// Return the existential deposit of [`Config::Currency`].
1652 fn min_balance() -> BalanceOf<T> {
1653 <T::Currency as Inspect<AccountIdOf<T>>>::minimum_balance()
1654 }
1655
1656 /// Convert gas_limit from 1D Weight to a 2D Weight.
1657 ///
1658 /// Used by backwards compatible extrinsics. We cannot just set the proof_size weight limit to
1659 /// zero or an old `Call` will just fail with OutOfGas.
1660 fn compat_weight_limit(gas_limit: OldWeight) -> Weight {
1661 Weight::from_parts(gas_limit, u64::from(T::MaxCodeLen::get()) * 2)
1662 }
1663}
1664
1665sp_api::decl_runtime_apis! {
1666 /// The API used to dry-run contract interactions.
1667 #[api_version(2)]
1668 pub trait ContractsApi<AccountId, Balance, BlockNumber, Hash, EventRecord> where
1669 AccountId: Codec,
1670 Balance: Codec,
1671 BlockNumber: Codec,
1672 Hash: Codec,
1673 EventRecord: Codec,
1674 {
1675 /// Perform a call from a specified account to a given contract.
1676 ///
1677 /// See [`crate::Pallet::bare_call`].
1678 fn call(
1679 origin: AccountId,
1680 dest: AccountId,
1681 value: Balance,
1682 gas_limit: Option<Weight>,
1683 storage_deposit_limit: Option<Balance>,
1684 input_data: Vec<u8>,
1685 ) -> ContractExecResult<Balance, EventRecord>;
1686
1687 /// Instantiate a new contract.
1688 ///
1689 /// See `[crate::Pallet::bare_instantiate]`.
1690 fn instantiate(
1691 origin: AccountId,
1692 value: Balance,
1693 gas_limit: Option<Weight>,
1694 storage_deposit_limit: Option<Balance>,
1695 code: Code<Hash>,
1696 data: Vec<u8>,
1697 salt: Vec<u8>,
1698 ) -> ContractInstantiateResult<AccountId, Balance, EventRecord>;
1699
1700 /// Upload new code without instantiating a contract from it.
1701 ///
1702 /// See [`crate::Pallet::bare_upload_code`].
1703 fn upload_code(
1704 origin: AccountId,
1705 code: Vec<u8>,
1706 storage_deposit_limit: Option<Balance>,
1707 determinism: Determinism,
1708 ) -> CodeUploadResult<Hash, Balance>;
1709
1710 /// Query a given storage key in a given contract.
1711 ///
1712 /// Returns `Ok(Some(Vec<u8>))` if the storage value exists under the given key in the
1713 /// specified account and `Ok(None)` if it doesn't. If the account specified by the address
1714 /// doesn't exist, or doesn't have a contract then `Err` is returned.
1715 fn get_storage(
1716 address: AccountId,
1717 key: Vec<u8>,
1718 ) -> GetStorageResult;
1719 }
1720}