contracts: Add RPC that allows instantiating of a contract (#8451)

* contracts: Add RPC that allows instantiating of a contract

* Encode `debug_message` as bytes because usage of `String` is forbidden

* Remove erroneous derive attribute

* Fix rpc tests for new `debug_message` encoding

* Fix typo

Co-authored-by: Andrew Jones <ascjones@gmail.com>

Co-authored-by: Andrew Jones <ascjones@gmail.com>
This commit is contained in:
Alexander Theißen
2021-04-13 13:26:52 +02:00
committed by GitHub
parent 24311eee3e
commit f854194139
16 changed files with 471 additions and 191 deletions
+47 -11
View File
@@ -32,17 +32,52 @@ use frame_support::{
weights::Weight,
ensure,
};
use pallet_contracts_primitives::{ErrorOrigin, ExecError, ExecReturnValue, ExecResult, ReturnFlags};
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
pub type MomentOf<T> = <<T as Config>::Time as Time>::Moment;
pub type SeedOf<T> = <T as frame_system::Config>::Hash;
pub type BlockNumberOf<T> = <T as frame_system::Config>::BlockNumber;
pub type StorageKey = [u8; 32];
pub type ExecResult = Result<ExecReturnValue, ExecError>;
/// A type that represents a topic of an event. At the moment a hash is used.
pub type TopicOf<T> = <T as frame_system::Config>::Hash;
/// Origin of the error.
///
/// Call or instantiate both called into other contracts and pass through errors happening
/// in those to the caller. This enum is for the caller to distinguish whether the error
/// happened during the execution of the callee or in the current execution context.
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum ErrorOrigin {
/// Caller error origin.
///
/// The error happened in the current exeuction context rather than in the one
/// of the contract that is called into.
Caller,
/// The error happened during execution of the called contract.
Callee,
}
/// Error returned by contract exection.
#[cfg_attr(test, derive(Debug, PartialEq))]
pub struct ExecError {
/// The reason why the execution failed.
pub error: DispatchError,
/// Origin of the error.
pub origin: ErrorOrigin,
}
impl<T: Into<DispatchError>> From<T> for ExecError {
fn from(error: T) -> Self {
Self {
error: error.into(),
origin: ErrorOrigin::Caller,
}
}
}
/// Information needed for rent calculations that can be requested by a contract.
#[derive(codec::Encode)]
#[cfg_attr(test, derive(Debug, PartialEq))]
@@ -945,6 +980,7 @@ mod tests {
exec::ExportedFunction::*,
Error, Weight, CurrentSchedule,
};
use sp_core::Bytes;
use frame_support::assert_noop;
use sp_runtime::DispatchError;
use assert_matches::assert_matches;
@@ -1123,7 +1159,7 @@ mod tests {
}
fn exec_success() -> ExecResult {
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) })
}
#[test]
@@ -1186,7 +1222,7 @@ mod tests {
let return_ch = MockLoader::insert(
Call,
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() })
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Bytes(Vec::new()) })
);
ExtBuilder::default().build().execute_with(|| {
@@ -1246,7 +1282,7 @@ mod tests {
let dest = BOB;
let return_ch = MockLoader::insert(
Call,
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] })
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(vec![1, 2, 3, 4]) })
);
ExtBuilder::default().build().execute_with(|| {
@@ -1263,7 +1299,7 @@ mod tests {
let output = result.unwrap();
assert!(output.0.is_success());
assert_eq!(output.0.data, vec![1, 2, 3, 4]);
assert_eq!(output.0.data, Bytes(vec![1, 2, 3, 4]));
});
}
@@ -1275,7 +1311,7 @@ mod tests {
let dest = BOB;
let return_ch = MockLoader::insert(
Call,
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![1, 2, 3, 4] })
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Bytes(vec![1, 2, 3, 4]) })
);
ExtBuilder::default().build().execute_with(|| {
@@ -1292,7 +1328,7 @@ mod tests {
let output = result.unwrap();
assert!(!output.0.is_success());
assert_eq!(output.0.data, vec![1, 2, 3, 4]);
assert_eq!(output.0.data, Bytes(vec![1, 2, 3, 4]));
});
}
@@ -1512,7 +1548,7 @@ mod tests {
fn instantiation_work_with_success_output() {
let dummy_ch = MockLoader::insert(
Constructor,
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: vec![80, 65, 83, 83] })
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(vec![80, 65, 83, 83]) })
);
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
@@ -1532,7 +1568,7 @@ mod tests {
vec![],
&[],
),
Ok((address, ref output)) if output.data == vec![80, 65, 83, 83] => address
Ok((address, ref output)) if output.data == Bytes(vec![80, 65, 83, 83]) => address
);
// Check that the newly created account has the expected code hash and
@@ -1548,7 +1584,7 @@ mod tests {
fn instantiation_fails_with_failing_output() {
let dummy_ch = MockLoader::insert(
Constructor,
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: vec![70, 65, 73, 76] })
|_, _| Ok(ExecReturnValue { flags: ReturnFlags::REVERT, data: Bytes(vec![70, 65, 73, 76]) })
);
ExtBuilder::default().existential_deposit(15).build().execute_with(|| {
@@ -1568,7 +1604,7 @@ mod tests {
vec![],
&[],
),
Ok((address, ref output)) if output.data == vec![70, 65, 73, 76] => address
Ok((address, ref output)) if output.data == Bytes(vec![70, 65, 73, 76]) => address
);
// Check that the account has not been created.