Commit 4107f98d authored by Hero Bird's avatar Hero Bird Committed by GitHub

Implementation of ink_env 2.0 (#195)

* [core] initial implementation of new env module

* [core] add SRML implementations for some more Env trait methods

* [core] replace SmallVec with Vec since it isn't ready yet

* [core] add license header to ret_code.rs

* [core] take generic buffer params &mut instead of by value

* [core] add implementation of create_contract for SRML env

* [core] remove unused SmallVec imports

* [core] implement deposit_event for SRML contracts env

* [core] implement invoke_runtime for SRML contract env

* [core] adjust invoke_runtime at trait level

* [core] implement restore_to for SRML contracts env

* [core] fix minor warnings and formatting issues

* [core] refactoring and clean ups

Output is no longer a contract property since it was too hard to make it work properly and efficiently.

* [core] add initial version of EnvAccess

* [core] add runtime checks to EnvAccess for input and output

* [core] GetProperty and SetProperty no longer return Result

* [core] introduce macro to remove some duplicate code in EnvAccess

* [core] make buffer always the first argument in Env

* [core] some minor clean ups

* [core] implement {get,set,clear}_contract_storage for EnvAccess

* [core] make assert_not_yet_returned and set_has_interacted private fns

* [core] implement EnvAccess::random

* [core] implement EnvAccess::println

* [core] implement EnvAccess::{invoke_contract, eval_contract, create_contract}

* [core] refactor module imports and exports

* [core] add DynEnv utility

* [core] move EnvAccess{Mut} into their own sub-module

* [core] improve docs and add docs where they were missing

* [core] add Default impl for EnvAccess

* [core] add DynEnv

* [core] greatly improve module docs

* [core] remove some warning-errors that were too strict

* [core] introduce initial implementation of test env

* [core] initial Storage implementation for TestEnv

* [core] improve module documentation

* [core] continue implementation of TestEnv

* [core] improve byte_utils docs for negate_bytes

* [core] add new DefaultSrmlTypes implementation

* [core] continue initial TestEnv implementation

* [core] add TypedEncoded utility that we might use in TestEnvInstance

* [core] enhance TypedEncoded utility

* [core] add Debug impl for Storage and Entry

* [core] implement the TestEnvInstance part of TestEnv

This is the part that actually holds the data in a generic fashion and is controlled later on by the TestEnv through thread_local storage.

* [core] remove unnecessary imports

* [core] remove unnecessary derive impls for some marker types

* [core] greatly improve doc comment of TestEnvInstance

* [core] implement Clone, PartialEq, Eq and Hash for any TypedEncoded<M>

* [ci] update Travis CI rust version: nightly-2019-08-30 -> nightly-2019-09-25

* [core] include TestEnv or SrmlEnv conditionally exclusively

* [core] apply rust fmt

* [core] use Input::remaining_len to optimize scale::Decode impl for CallData

* [core] align usage of PhantomData

* [core] resolve call/create TODOs

* [core] fix minor doc issues

* [core] add a note to Env::println to make users aware of it being a debug utility

* [core] apply rust fmt

* [core] add Debug impl to Storage and Entry

* [core] add PartialOrd and Ord impl to TypedEncoded

* [core] split TestEnv TypedEncoded types into their own module

* [core] add an account database for the TestEnv

* [core] move impl_get_property_for next to its macro definition

* [core] enhance test::AccountsDb

* [core] make fields in TestEnvInstance pub

* [core] fix some mod re-exports

* [core] improve AccountsDb get and get_mut interface

* [core] add TypedEncoded::{assign, try_assign} methods

* [core] add 'static to all EnvTypes associated types

* [core] add initial implementation of accessor for TestEnvInstance

* [core] rename some fields in instance.rs

* [core] implement the rest of the properties getters and setters for TestEnv

* [core] move Input property getter into macro

* [core] add initial stubs for Env impl of TestEnv

* [core] slightly improve property getters

* [core] implement Env::get_contract_storage for TestEnv

* [ci] update nightly-2019-09-25 -> nightly-2019-10-03

* [core] improve Storage::write by using Entry API

* [core] silence warning of unused buffer in Env impl for TestEnv

* [core] implement Env::set_contract_storage for TestEnv

* [core] impl Env::clear_contract_storage for TestEnv

* [core] add dev-comments for implementations of many Env methods for TestEnv

These need some explanation since they partly contradict the off-chain nature of the TestEnv.

* [core] implement Env::random for TestEnv

* [core] improve dev-comment for Env::create_contract

* [core] implement Env::output for TestEnv

* [core] add AccountIdGen to TestEnvInstance

* [core] add records to test environment module

Used for later use in recording implementations of Env for TestEnv.

* [core] apply rustfmt

* [core] fix some warnings

* [core] add constructors for records

* [core] make record constructors pub

* [core] apply rustfmt

* [core] implement Env::{invoke_contract, eval_contract} for TestEnv

* [core] implement restoration and runtime invokation records

* [core] implement Env::{emit_event, invoke_runtime, restore_to} for TestEnv

* [core] implement AccountsDb::insert

* [core] implement Env::create_contract for TestEnv

* [core] add doc-comment for test environment module

* [core] fix copy/paste error in accessor.rs

* [core] add initialization routines to TestEnvInstance

* [core] make use of TypedEncoded in record.rs

* [core] re-export concrete Env impls as EnvImpl

* [core] make most of the test environment definitions publicly visible

* [core] apply rustfmt

* [core] fix 2 compile errors in no_std mode

* [core] add doc-comments to all test sub-modules

* [core] add doc-comments to EnvImpl type alias

* [core] add initial implementation of TestEnv::try_initialize

* [core] add dev-notes to SrmlEnv

* [ci] update travis nightly usage nightly-2019-10-03 -> nightly-2019-10-04
parent d92462b3
......@@ -7,7 +7,7 @@ rust:
# - stable
# - beta
- nightly
- nightly-2019-08-30
- nightly-2019-10-04
matrix:
allow_failures:
......
......@@ -24,16 +24,22 @@ ink_utils = { path = "../utils/", default-features = false }
scale = { package = "parity-scale-codec", version = "1.0", default-features = false, features = ["derive", "full"] }
type-metadata = { git = "https://github.com/type-metadata/type-metadata.git", default-features = false, features = ["derive"], optional = true }
derive_more = { version = "0.15", default-features = false, features = ["no_std"] }
smallvec = { version = "0.6.10", default-features = false, features = ["union"] }
cfg-if = "0.1"
[features]
default = ["test-env"]
test-env = ["std"]
test-env = [
"std",
]
std = [
"ink_abi/std",
"ink_alloc/std",
"ink_utils/std",
"scale/std",
"type-metadata/std",
"smallvec/std",
]
ink-generate-abi = [
"ink_abi",
......
......@@ -25,7 +25,7 @@ fn invert_bytes(bytes: &mut [u8]) {
/// Negate the given bytes inplace.
///
/// Interprets the bytes as twos-complement number.
/// Interprets the bytes as big endian twos-complement number.
pub fn negate_bytes(bytes: &mut [u8]) {
invert_bytes(bytes);
bytes_add_bytes(bytes, &[0x01]);
......
This diff is collapsed.
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::{
env2::{
EnvAccess,
EnvAccessMut,
},
storage::{
alloc::{
Allocate,
AllocateUsing,
DynAlloc,
Initialize,
},
Flush,
},
};
use core::ops::{
Deref,
DerefMut,
};
/// Environment with `&self` access and a dynamic allocator.
///
/// # Note
///
/// - Accesses to `DynEnvAccess` are checked at runtime.
/// - The dynamic allocator allows to dynamically allocate and deallocate objects on the storage.
pub type DynEnvAccess<E> = DynEnv<EnvAccess<E>>;
/// Environment with `&mut self`-only access and a dynamic allocator.
///
/// # Note
///
/// - Accesses to `DynEnvAccessMut` are checked at compiletime.
/// - The dynamic allocator allows to dynamically allocate and deallocate objects on the storage.
pub type DynEnvAccessMut<E> = DynEnv<EnvAccessMut<E>>;
/// A wrapper around `EnvAccess` or `EnvAccessMut` that adds a dynamic storage allocator.
pub struct DynEnv<E> {
/// The wrapped environment.
env: E,
/// The dynamic storage allocator.
alloc: DynAlloc,
}
impl<E> Deref for DynEnv<E> {
type Target = E;
fn deref(&self) -> &Self::Target {
&self.env
}
}
impl<E> DerefMut for DynEnv<E> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.env
}
}
impl<E> Flush for DynEnv<E> {
fn flush(&mut self) {
self.alloc.flush()
}
}
impl<E> AllocateUsing for DynEnv<E>
where
E: Default,
{
unsafe fn allocate_using<A>(alloc: &mut A) -> Self
where
A: Allocate,
{
Self {
env: Default::default(),
alloc: AllocateUsing::allocate_using(alloc),
}
}
}
impl<E> Initialize for DynEnv<E> {
type Args = ();
fn initialize(&mut self, _args: Self::Args) {
self.alloc.initialize(());
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::{
env2::{
call::CallData,
CallParams,
CreateParams,
Env,
EnvAccessMut,
Result,
},
storage::Key,
};
use core::cell::RefCell;
/// A `&self` accessor to `EnvAccessMut`.
///
/// This allows ink! `&self` messages to make use of the environment efficiently
/// while also maintaining access invariants through runtime checks.
/// A wrapper arround `EnvAccessMut` allowing for `&self` accesses to make it
/// usable in `&self` ink! messages.
///
/// # Note
///
/// Using `EnvAccessMut` is preferable since it performs these access checks at
/// compile-time.
pub struct EnvAccess<T> {
/// Allows accessing the inner environment by `&self` instead of `&mut self`.
///
/// This is important to make `DynEnv` work also in conjunction with `&self` messages.
access: RefCell<EnvAccessMut<T>>,
}
impl<T> Default for EnvAccess<T> {
fn default() -> Self {
Self {
access: RefCell::new(Default::default()),
}
}
}
impl<T> From<EnvAccessMut<T>> for EnvAccess<T> {
fn from(env_access_mut: EnvAccessMut<T>) -> Self {
Self {
access: RefCell::new(env_access_mut),
}
}
}
macro_rules! impl_forward_for {
(
$( #[$meta:meta] )*
fn $fn_name:ident $( < $($gen_arg:ident),* > )? ( &self $(, $arg_name:ident : $arg_ty:ty )* )
$(
where
$(
$bound_ident:ident : $bound_ty:path
),*
)?
;
$($tt:tt)*
) => {
impl_forward_for!(
$( #[$meta] )*
fn $fn_name $( < $($gen_arg),* > )? ( &self $(, $arg_name : $arg_ty )* ) -> ()
$(
where
$(
$bound_ident : $bound_ty
),*
)?
;
$($tt)*
);
};
(
$( #[$meta:meta] )*
fn $fn_name:ident $( < $($gen_arg:ident),* > )? ( &self $(, $arg_name:ident : $arg_ty:ty )* ) -> $ret:ty
$(
where
$(
$bound_ident:ident : $bound_ty:path
),*
)?
;
$($tt:tt)*
) => {
$( #[$meta] )*
pub fn $fn_name $( < $($gen_arg),* > )? (&self $(, $arg_name : $arg_ty)* ) -> $ret
$(
where
$(
$bound_ident : $bound_ty
),*
)?
{
self.access.borrow_mut().$fn_name( $($arg_name),* )
}
impl_forward_for!($($tt)*);
};
() => {};
}
impl<T> EnvAccess<T>
where
T: Env,
{
impl_forward_for! {
/// Returns the address of the caller of the executed contract.
fn caller(&self) -> T::AccountId;
/// Returns the transferred balance for the contract execution.
fn transferred_balance(&self) -> T::Balance;
/// Returns the current price for gas.
fn gas_price(&self) -> T::Balance;
/// Returns the amount of gas left for the contract execution.
fn gas_left(&self) -> T::Balance;
/// Returns the current block time in milliseconds.
fn now_in_ms(&self) -> T::Moment;
/// Returns the address of the executed contract.
fn address(&self) -> T::AccountId;
/// Returns the balance of the executed contract.
fn balance(&self) -> T::Balance;
/// Returns the current rent allowance for the executed contract.
fn rent_allowance(&self) -> T::Balance;
/// Returns the current block number.
fn block_number(&self) -> T::BlockNumber;
/// Returns the minimum balance of the executed contract.
fn minimum_balance(&self) -> T::Balance;
/// Sets the rent allowance of the executed contract to the new value.
fn set_rent_allowance(&self, new_value: T::Balance);
/// Writes the value to the contract storage under the given key.
fn set_contract_storage<V>(&self, key: Key, value: &V)
where
V: scale::Encode;
/// Returns the value stored under the given key in the contract's storage.
///
/// # Errors
///
/// - If the key's entry is empty
/// - If the decoding of the typed value failed
fn get_contract_storage<R>(&self, key: Key) -> Result<R>
where
R: scale::Decode;
/// Clears the contract's storage key entry.
fn clear_contract_storage(&self, key: Key);
/// Invokes a contract message.
///
/// # Errors
///
/// If the called contract has trapped.
fn invoke_contract<D>(&self, call_data: &D) -> Result<()>
where
D: CallParams<T>;
/// Evaluates a contract message and returns its result.
///
/// # Errors
///
/// - If the called contract traps.
/// - If the account ID is invalid.
/// - If given too little endowment.
/// - If arguments passed to the called contract are invalid.
/// - If the called contract runs out of gas.
fn eval_contract<D, R>(&self, call_data: &D) -> Result<R>
where
D: CallParams<T>,
R: scale::Decode;
/// Instantiates another contract.
///
/// # Errors
///
/// - If the instantiation process traps.
/// - If the code hash is invalid.
/// - If given too little endowment.
/// - If the instantiation process runs out of gas.
fn create_contract<D>(&self, create_data: &D) -> Result<T::AccountId>
where
D: CreateParams<T>;
/// Returns the input to the executed contract.
///
/// # Note
///
/// - The input is the 4-bytes selector followed by the arguments
/// of the called function in their SCALE encoded representation.
/// - This property must be received as the first action an executed
/// contract to its environment and can only be queried once.
/// The environment access asserts this guarantee.
fn input(&self) -> CallData;
/// Returns the value back to the caller of the executed contract.
///
/// # Note
///
/// The setting of this property must be the last interaction between
/// the executed contract and its environment.
/// The environment access asserts this guarantee.
fn output<R>(&self, return_value: &R)
where
R: scale::Encode;
/// Returns a random hash.
///
/// # Note
///
/// The subject buffer can be used to further randomize the hash.
fn random(&self, subject: &[u8]) -> T::Hash;
/// Prints the given contents to the environmental log.
fn println(&self, content: &str);
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
mod immutable;
mod mutable;
pub use self::{
immutable::EnvAccess,
mutable::EnvAccessMut,
};
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
use crate::{
env2::{
call::CallData,
property,
CallParams,
CreateParams,
Env,
EnvTypes,
GetProperty,
Result,
SetProperty,
},
memory::vec::Vec,
storage::Key,
};
use core::marker::PhantomData;
/// A wrapper around environments to make accessing them more efficient.
pub struct EnvAccessMut<E> {
/// The wrapped environment to access.
env: PhantomData<E>,
/// A buffer to make environment accesses
/// more efficient by avoiding allocations.
buffer: Vec<u8>,
/// False as long as there has been no interaction between
/// the executed contract and the environment.
///
/// This flag is used to check at runtime if the environment
/// is used correctly in respect to accessing its input.
has_interacted: bool,
/// True as long as the return value has not yet been set.
///
/// This flag is used to check at runtime if the environment
/// is used correctly in respect to returning its value.
has_returned_value: bool,
}
impl<E> Default for EnvAccessMut<E> {
fn default() -> Self {
Self {
env: Default::default(),
buffer: Default::default(),
has_interacted: false,
has_returned_value: false,
}
}
}
impl<T> EnvTypes for EnvAccessMut<T>
where
T: EnvTypes,
{
/// The type of an address.
type AccountId = T::AccountId;
/// The type of balances.
type Balance = T::Balance;
/// The type of hash.
type Hash = T::Hash;
/// The type of timestamps.
type Moment = T::Moment;
/// The type of block number.
type BlockNumber = T::BlockNumber;
/// The type of a call into the runtime
type Call = T::Call;
}
macro_rules! impl_get_property_for {
(
$( #[$meta:meta] )*
fn $fn_name:ident< $prop_name:ident >() -> $ret:ty; $($tt:tt)*
) => {
$( #[$meta] )*
pub fn $fn_name(&mut self) -> $ret {
self.assert_not_yet_returned();
self.set_has_interacted();
<T as GetProperty<property::$prop_name<T>>>::get_property(&mut self.buffer)
}
impl_get_property_for!($($tt)*);
};
() => {}
}
impl<T> EnvAccessMut<T>
where
T: Env,
{
/// Asserts that no value has been returned yet by the contract execution.
fn assert_not_yet_returned(&self) {
assert!(!self.has_returned_value)
}
/// Sets the flag for recording interaction between executed contract
/// and environment to `true`.
fn set_has_interacted(&mut self) {
self.has_interacted = true;
}
impl_get_property_for! {
/// Returns the address of the caller of the executed contract.
fn caller<Caller>() -> T::AccountId;
/// Returns the transferred balance for the contract execution.
fn transferred_balance<TransferredBalance>() -> T::Balance;
/// Returns the current price for gas.
fn gas_price<GasPrice>() -> T::Balance;
/// Returns the amount of gas left for the contract execution.
fn gas_left<GasLeft>() -> T::Balance;
/// Returns the current block time in milliseconds.
fn now_in_ms<NowInMs>() -> T::Moment;
/// Returns the address of the executed contract.
fn address<Address>() -> T::AccountId;
/// Returns the balance of the executed contract.
fn balance<Balance>() -> T::Balance;
/// Returns the current rent allowance for the executed contract.
fn rent_allowance<RentAllowance>() -> T::Balance;
/// Returns the current block number.
fn block_number<BlockNumber>() -> T::BlockNumber;
/// Returns the minimum balance of the executed contract.
fn minimum_balance<MinimumBalance>() -> T::Balance;
}
/// Sets the rent allowance of the executed contract to the new value.
pub fn set_rent_allowance(&mut self, new_value: T::Balance) {
self.assert_not_yet_returned();
self.set_has_interacted();
<T as SetProperty<property::RentAllowance<T>>>::set_property(
&mut self.buffer,
&new_value,
)
}
/// Writes the value to the contract storage under the given key.
pub fn set_contract_storage<V>(&mut self, key: Key, value: &V)
where
V: scale::Encode,
{
T::set_contract_storage(&mut self.buffer, key, value)
}
/// Returns the value stored under the given key in the contract's storage.
///
/// # Errors
///
/// - If the key's entry is empty
/// - If the decoding of the typed value failed
pub fn get_contract_storage<R>(&mut self, key: Key) -> Result<R>
where
R: scale::Decode,
{
T::get_contract_storage(&mut self.buffer, key)
}
/// Clears the contract's storage key entry.
pub fn clear_contract_storage(&mut self, key: Key) {
T::clear_contract_storage(key)
}
/// Invokes a contract message.
///
/// # Errors
///
/// If the called contract has trapped.
pub fn invoke_contract<D>(&mut self, call_data: &D) -> Result<()>
where
D: CallParams<T>,
{
T::invoke_contract(&mut self.buffer, call_data)
}
/// Evaluates a contract message and returns its result.
///
/// # Errors
///
/// - If the called contract traps.
/// - If the account ID is invalid.
/// - If given too few endowment.
/// - If arguments passed to the called contract are invalid.
/// - If the called contract runs out of gas.
pub fn eval_contract<D, R>(&mut self, call_data: &D) -> Result<R>
where
D: CallParams<T>,
R: scale::Decode,
{
T::eval_contract(&mut self.buffer, call_data)
}
/// Instantiates another contract.
///
/// # Errors
///
/// - If the instantiation process traps.
/// - If the code hash is invalid.
/// - If given too few endowment.
/// - If the instantiation process runs out of gas.
pub fn create_contract<D>(&mut self, create_data: &D) -> Result<T::AccountId>
where
D: CreateParams<T>,
{
T::create_contract(&mut self.buffer, create_data)
}
/// Returns the input to the executed contract.
///
/// # Note
///
/// - The input is the 4-bytes selector followed by the arguments
/// of the called function in their SCALE encoded representation.
/// - This property must be received as the first action an executed
/// contract to its environment and can only be queried once.
/// The environment access asserts this guarantee.
pub fn input(&mut self) -> CallData {
assert!(!self.has_interacted);
self.assert_not_yet_returned();
self.set_has_interacted();
<T as GetProperty<property::Input<T>>>::get_property(&mut self.buffer)
}
/// Returns the value back to the caller of the executed contract.
///
/// # Note
///
/// The setting of this property must be the last interaction between
/// the executed contract and its environment.
/// The environment access asserts this guarantee.
pub fn output<R>(&mut self, return_value: &R)
where
R: scale::Encode,
{
self.assert_not_yet_returned();
self.set_has_interacted();
self.has_returned_value = true;
T::output(&mut self.buffer, &return_value);
}
/// Returns a random hash.
///
/// # Note
///
/// The subject buffer can be used to further randomize the hash.
pub fn random(&mut self, subject: &[u8]) -> T::Hash {
self.assert_not_yet_returned();
self.set_has_interacted();
T::random(&mut self.buffer, subject)
}
/// Prints the given contents to the environmental log.
pub fn println(&mut self, content: &str) {
T::println(content)
}
}
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
// This file is part of ink!.
//
// ink! is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ink! is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see <http://www.gnu.org/licenses/>.
//! Error definitions specific to environment accesses.
use derive_more::From;
/// Error encountered by calling a remote contract.
///
/// # Note
///
/// This is currently just a placeholder for potential future error codes.
#[derive(Debug, Copy, Clone)]
pub struct CallError;
/// Error encountered upon creating and instantiation a new smart contract.
///
/// # Note
///
/// This is currently just a placeholder for potential future error codes.
#[derive(Debug, Copy, Clone)]
pub struct CreateError;
/// Errors that can be encountered while accessing the contract's environment.
#[derive(Debug, Clone, From)]
pub enum Error {
Call(CallError),
Create(CreateError),
Codec(scale::Error),
InvalidStorageKey,
InvalidStorageRead,
InvalidContractCall,
InvalidContractCallReturn,