Newer
Older
// This file is part of Substrate.
// Copyright (C) Parity Technologies (UK) Ltd.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Sasha Gryaznov
committed
//! # Contracts Pallet
Sasha Gryaznov
committed
//! The Contracts module provides functionality for the runtime to deploy and execute WebAssembly
//! This module extends accounts based on the [`Currency`] trait to have smart-contract
//! functionality. It can be used with other modules that implement accounts based on [`Currency`].
//! These "smart-contract accounts" have the ability to instantiate smart-contracts and make calls
//! to other contract and non-contract accounts.
//! The smart-contract code is stored once, and later retrievable via its hash.
//! This means that multiple smart-contracts can be instantiated from the same hash, without
//! replicating the code each time.
//! When a smart-contract is called, its associated code is retrieved via the code hash and gets
//! executed. This call can alter the storage entries of the smart-contract account, instantiate new
//! smart-contracts, or call other smart-contracts.
//! Finally, when an account is reaped, its associated code and storage of the smart-contract
//! account will also be deleted.
//! Senders must specify a [`Weight`] limit with every call, as all instructions invoked by the
//! smart-contract require weight. Unused weight is refunded after the call, regardless of the
//! execution outcome.
//! If the weight limit is reached, then all calls and state changes (including balance transfers)
//! are only reverted at the current call's contract level. For example, if contract A calls B and B
//! runs out of gas mid-call, then all of B's calls are reverted. Assuming correct error handling by
//! contract A, A's other calls and state changes still persist.
//! Contract call failures are not always cascading. When failures occur in a sub-call, they do not
//! "bubble up", and the call will only revert at the specific contract level. For example, if
//! contract A calls contract B, and B fails, A can decide how to handle that failure, either
//! proceeding or reverting A's changes.
//! * [`Pallet::instantiate_with_code`] - Deploys a new contract from the supplied Wasm binary,
//! optionally transferring
//! some balance. This instantiates a new smart contract account with the supplied code and
//! calls its constructor to initialize the contract.
//! * [`Pallet::instantiate`] - The same as `instantiate_with_code` but instead of uploading new
//! code an existing `code_hash` is supplied.
//! * [`Pallet::call`] - Makes a call to an account, optionally transferring some balance.
//! * [`Pallet::upload_code`] - Uploads new code without instantiating a contract from it.
//! * [`Pallet::remove_code`] - Removes the stored code and refunds the deposit to its owner. Only
//! allowed to code owner.
//! * [`Pallet::set_code`] - Changes the code of an existing contract. Only allowed to `Root`
//! origin.
//! * [`Pallet::migrate`] - Runs migration steps of current multi-block migration in priority,
//! before [`Hooks::on_idle`][frame_support::traits::Hooks::on_idle] activates.
//! * [`ink!`](https://use.ink) is language that enables writing Wasm-based smart contracts in plain
//! Rust.
#![allow(rustdoc::private_intra_doc_links)]
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "1024")]
Alexander Theißen
committed
mod address;
mod schedule;
pub mod chain_extension;
pub mod weights;
#[cfg(test)]
mod tests;
use crate::{
exec::{AccountIdOf, ErrorOrigin, ExecError, Executable, Key, Stack as ExecStack},
PG Herveou
committed
storage::{meter::Meter as StorageMeter, ContractInfo, DeletionQueueManager},
wasm::{CodeInfo, WasmBlob},
use codec::{Codec, Decode, Encode, HasCompact};
Sasha Gryaznov
committed
use environmental::*;
dispatch::{
DispatchError, Dispatchable, GetDispatchInfo, Pays, PostDispatchInfo, RawOrigin,
WithPostDispatchInfo,
},
ensure,
Alexander Theißen
committed
traits::{
tokens::fungible::Inspect, ConstU32, Contains, Currency, Get, Randomness,
ReservableCurrency, Time,
},
BoundedVec, RuntimeDebugNoBound,
use frame_system::{ensure_signed, pallet_prelude::OriginFor, EventRecord, Pallet as System};
Alexander Theißen
committed
use pallet_contracts_primitives::{
Code, CodeUploadResult, CodeUploadReturnValue, ContractAccessError, ContractExecResult,
ContractInstantiateResult, ContractResult, ExecReturnValue, GetStorageResult,
InstantiateReturnValue, StorageDeposit,
use smallvec::Array;
use sp_runtime::traits::{Convert, Hash, Saturating, StaticLookup, Zero};
use sp_std::{fmt::Debug, prelude::*};
pub use crate::{
Alexander Theißen
committed
address::{AddressGenerator, DefaultAddressGenerator},
exec::Frame,
migration::{MigrateSequence, Migration, NoopMigration},
pallet::*,
schedule::{HostFnWeights, InstructionWeights, Limits, Schedule},
wasm::Determinism,
};
Sasha Gryaznov
committed
#[cfg(doc)]
pub use crate::wasm::api_doc;
type CodeHash<T> = <T as frame_system::Config>::Hash;
type TrieId = BoundedVec<u8, ConstU32<128>>;
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
type CodeVec<T> = BoundedVec<u8, <T as Config>::MaxCodeLen>;
type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
type DebugBufferVec<T> = BoundedVec<u8, <T as Config>::MaxDebugBufferLen>;
type EventRecordOf<T> =
EventRecord<<T as frame_system::Config>::RuntimeEvent, <T as frame_system::Config>::Hash>;
/// The old weight type.
///
/// This is a copy of the [`frame_support::weights::OldWeight`] type since the contracts pallet
/// needs to support it indefinitely.
type OldWeight = u64;
/// Used as a sentinel value when reading and writing contract memory.
///
/// It is usually used to signal `None` to a contract when only a primitive is allowed
/// and we don't want to go through encoding a full Rust type. Using `u32::Max` is a safe
/// sentinel because contracts are never allowed to use such a large amount of resources
/// that this value makes sense for a memory location or length.
const SENTINEL: u32 = u32::MAX;
/// The target that is used for the log output emitted by this crate.
///
/// Hence you can use this target to selectively increase the log level for this crate.
///
/// Example: `RUST_LOG=runtime::contracts=debug my_code --dev`
const LOG_TARGET: &str = "runtime::contracts";
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
/// The current storage version.
#[cfg(not(any(test, feature = "runtime-benchmarks")))]
const STORAGE_VERSION: StorageVersion = StorageVersion::new(12);
/// Hard coded storage version for running tests that depend on the current storage version.
#[cfg(any(test, feature = "runtime-benchmarks"))]
const STORAGE_VERSION: StorageVersion = StorageVersion::new(2);
#[pallet::pallet]
#[pallet::storage_version(STORAGE_VERSION)]
pub struct Pallet<T>(_);
#[pallet::config]
pub trait Config: frame_system::Config {
Loading full blame...