mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-16 16:41:10 +00:00
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:
committed by
GitHub
parent
24311eee3e
commit
f854194139
@@ -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.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::{Config, Error};
|
||||
use crate::{Config, Error, exec::ExecError};
|
||||
use sp_std::marker::PhantomData;
|
||||
use sp_runtime::traits::Zero;
|
||||
use frame_support::{
|
||||
@@ -24,7 +24,6 @@ use frame_support::{
|
||||
},
|
||||
weights::Weight,
|
||||
};
|
||||
use pallet_contracts_primitives::ExecError;
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -112,7 +112,7 @@ use crate::{
|
||||
weights::WeightInfo,
|
||||
wasm::PrefabWasmModule,
|
||||
};
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
use sp_core::{Bytes, crypto::UncheckedFrom};
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::{
|
||||
traits::{
|
||||
@@ -127,6 +127,7 @@ use frame_support::{
|
||||
use frame_system::Pallet as System;
|
||||
use pallet_contracts_primitives::{
|
||||
RentProjectionResult, GetStorageResult, ContractAccessError, ContractExecResult,
|
||||
ContractInstantiateResult, Code, InstantiateReturnValue,
|
||||
};
|
||||
|
||||
type CodeHash<T> = <T as frame_system::Config>::Hash;
|
||||
@@ -666,8 +667,8 @@ where
|
||||
{
|
||||
/// Perform a call to a specified contract.
|
||||
///
|
||||
/// This function is similar to `Self::call`, but doesn't perform any address lookups and better
|
||||
/// suitable for calling directly from Rust.
|
||||
/// This function is similar to [`Self::call`], but doesn't perform any address lookups
|
||||
/// and better suitable for calling directly from Rust.
|
||||
///
|
||||
/// It returns the execution result and the amount of used weight.
|
||||
pub fn bare_call(
|
||||
@@ -683,8 +684,65 @@ where
|
||||
let result = ctx.call(dest, value, &mut gas_meter, input_data);
|
||||
let gas_consumed = gas_meter.gas_spent();
|
||||
ContractExecResult {
|
||||
exec_result: result.map(|r| r.0).map_err(|r| r.0),
|
||||
result: result.map(|r| r.0).map_err(|r| r.0.error),
|
||||
gas_consumed,
|
||||
debug_message: Bytes(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Instantiate a new contract.
|
||||
///
|
||||
/// This function is similar to [`Self::instantiate`], but doesn't perform any address lookups
|
||||
/// and better suitable for calling directly from Rust.
|
||||
///
|
||||
/// It returns the execution result, account id and the amount of used weight.
|
||||
///
|
||||
/// If `compute_projection` is set to `true` the result also contains the rent projection.
|
||||
/// This is optional because some non trivial and stateful work is performed to compute
|
||||
/// the projection. See [`Self::rent_projection`].
|
||||
pub fn bare_instantiate(
|
||||
origin: T::AccountId,
|
||||
endowment: BalanceOf<T>,
|
||||
gas_limit: Weight,
|
||||
code: Code<CodeHash<T>>,
|
||||
data: Vec<u8>,
|
||||
salt: Vec<u8>,
|
||||
compute_projection: bool,
|
||||
) -> ContractInstantiateResult<T::AccountId, T::BlockNumber> {
|
||||
let mut gas_meter = GasMeter::new(gas_limit);
|
||||
let schedule = <CurrentSchedule<T>>::get();
|
||||
let mut ctx = ExecutionContext::<T, PrefabWasmModule<T>>::top_level(origin, &schedule);
|
||||
let executable = match code {
|
||||
Code::Upload(Bytes(binary)) => PrefabWasmModule::from_code(binary, &schedule),
|
||||
Code::Existing(hash) => PrefabWasmModule::from_storage(hash, &schedule, &mut gas_meter),
|
||||
};
|
||||
let executable = match executable {
|
||||
Ok(executable) => executable,
|
||||
Err(error) => return ContractInstantiateResult {
|
||||
result: Err(error.into()),
|
||||
gas_consumed: gas_meter.gas_spent(),
|
||||
debug_message: Bytes(Vec::new()),
|
||||
}
|
||||
};
|
||||
let result = ctx.instantiate(endowment, &mut gas_meter, executable, data, &salt)
|
||||
.and_then(|(account_id, result)| {
|
||||
let rent_projection = if compute_projection {
|
||||
Some(Rent::<T, PrefabWasmModule<T>>::compute_projection(&account_id)
|
||||
.map_err(|_| <Error<T>>::NewContractNotFunded)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(InstantiateReturnValue {
|
||||
result,
|
||||
account_id,
|
||||
rent_projection,
|
||||
})
|
||||
});
|
||||
ContractInstantiateResult {
|
||||
result: result.map_err(|e| e.error),
|
||||
gas_consumed: gas_meter.gas_spent(),
|
||||
debug_message: Bytes(Vec::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -388,7 +388,7 @@ where
|
||||
None | Some(ContractInfo::Tombstone(_)) => return Err(IsTombstone),
|
||||
Some(ContractInfo::Alive(contract)) => contract,
|
||||
};
|
||||
let module = PrefabWasmModule::from_storage_noinstr(alive_contract_info.code_hash)
|
||||
let module = <PrefabWasmModule<T>>::from_storage_noinstr(alive_contract_info.code_hash)
|
||||
.map_err(|_| IsTombstone)?;
|
||||
let code_size = module.occupied_storage();
|
||||
let current_block_number = <frame_system::Pallet<T>>::block_number();
|
||||
@@ -399,8 +399,11 @@ where
|
||||
&alive_contract_info,
|
||||
code_size,
|
||||
);
|
||||
|
||||
// We skip the eviction in case one is in order.
|
||||
// Evictions should only be performed by [`try_eviction`].
|
||||
let new_contract_info = Self::enact_verdict(
|
||||
account, alive_contract_info, current_block_number, verdict, Some(module),
|
||||
account, alive_contract_info, current_block_number, verdict, None,
|
||||
);
|
||||
|
||||
// Check what happened after enaction of the verdict.
|
||||
|
||||
@@ -30,6 +30,7 @@ use crate::{
|
||||
};
|
||||
use assert_matches::assert_matches;
|
||||
use codec::Encode;
|
||||
use sp_core::Bytes;
|
||||
use sp_runtime::{
|
||||
traits::{BlakeTwo256, Hash, IdentityLookup, Convert},
|
||||
testing::{Header, H256},
|
||||
@@ -1886,7 +1887,7 @@ fn crypto_hashes() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
params,
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert!(result.is_success());
|
||||
let expected = hash_fn(input.as_ref());
|
||||
assert_eq!(&result.data[..*expected_size], &*expected);
|
||||
@@ -1921,7 +1922,7 @@ fn transfer_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
vec![],
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||
|
||||
// Contract has enough total balance in order to not go below the subsistence
|
||||
@@ -1935,7 +1936,7 @@ fn transfer_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
vec![],
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||
});
|
||||
}
|
||||
@@ -1969,7 +1970,7 @@ fn call_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
AsRef::<[u8]>::as_ref(&DJANGO).to_vec(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::NotCallable);
|
||||
|
||||
assert_ok!(
|
||||
@@ -1992,7 +1993,7 @@ fn call_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&0u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||
|
||||
// Contract has enough total balance in order to not go below the subsistence
|
||||
@@ -2006,7 +2007,7 @@ fn call_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&0u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||
|
||||
// Contract has enough balance but callee reverts because "1" is passed.
|
||||
@@ -2017,7 +2018,7 @@ fn call_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&1u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
||||
|
||||
// Contract has enough balance but callee traps because "2" is passed.
|
||||
@@ -2027,7 +2028,7 @@ fn call_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
AsRef::<[u8]>::as_ref(&addr_django).iter().chain(&2u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
||||
|
||||
});
|
||||
@@ -2074,7 +2075,7 @@ fn instantiate_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
callee_hash.clone(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::BelowSubsistenceThreshold);
|
||||
|
||||
// Contract has enough total balance in order to not go below the subsistence
|
||||
@@ -2088,7 +2089,7 @@ fn instantiate_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
callee_hash.clone(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::TransferFailed);
|
||||
|
||||
// Contract has enough balance but the passed code hash is invalid
|
||||
@@ -2099,7 +2100,7 @@ fn instantiate_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
vec![0; 33],
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::CodeNotFound);
|
||||
|
||||
// Contract has enough balance but callee reverts because "1" is passed.
|
||||
@@ -2109,7 +2110,7 @@ fn instantiate_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
callee_hash.iter().chain(&1u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::CalleeReverted);
|
||||
|
||||
// Contract has enough balance but callee traps because "2" is passed.
|
||||
@@ -2119,7 +2120,7 @@ fn instantiate_return_code() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
callee_hash.iter().chain(&2u32.to_le_bytes()).cloned().collect(),
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_return_code!(result, RuntimeReturnCode::CalleeTrapped);
|
||||
|
||||
});
|
||||
@@ -2209,7 +2210,7 @@ fn chain_extension_works() {
|
||||
);
|
||||
let gas_consumed = result.gas_consumed;
|
||||
assert_eq!(TestExtension::last_seen_buffer(), vec![0, 99]);
|
||||
assert_eq!(result.exec_result.unwrap().data, vec![0, 99]);
|
||||
assert_eq!(result.result.unwrap().data, Bytes(vec![0, 99]));
|
||||
|
||||
// 1 = treat inputs as integer primitives and store the supplied integers
|
||||
Contracts::bare_call(
|
||||
@@ -2218,7 +2219,7 @@ fn chain_extension_works() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
vec![1],
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
// those values passed in the fixture
|
||||
assert_eq!(TestExtension::last_seen_inputs(), (4, 1, 16, 12));
|
||||
|
||||
@@ -2230,7 +2231,7 @@ fn chain_extension_works() {
|
||||
GAS_LIMIT,
|
||||
vec![2, 42],
|
||||
);
|
||||
assert_ok!(result.exec_result);
|
||||
assert_ok!(result.result);
|
||||
assert_eq!(result.gas_consumed, gas_consumed + 42);
|
||||
|
||||
// 3 = diverging chain extension call that sets flags to 0x1 and returns a fixed buffer
|
||||
@@ -2240,9 +2241,9 @@ fn chain_extension_works() {
|
||||
0,
|
||||
GAS_LIMIT,
|
||||
vec![3],
|
||||
).exec_result.unwrap();
|
||||
).result.unwrap();
|
||||
assert_eq!(result.flags, ReturnFlags::REVERT);
|
||||
assert_eq!(result.data, vec![42, 99]);
|
||||
assert_eq!(result.data, Bytes(vec![42, 99]));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2767,7 +2768,7 @@ fn reinstrument_does_charge() {
|
||||
GAS_LIMIT,
|
||||
zero.clone(),
|
||||
);
|
||||
assert!(result0.exec_result.unwrap().is_success());
|
||||
assert!(result0.result.unwrap().is_success());
|
||||
|
||||
let result1 = Contracts::bare_call(
|
||||
ALICE,
|
||||
@@ -2776,7 +2777,7 @@ fn reinstrument_does_charge() {
|
||||
GAS_LIMIT,
|
||||
zero.clone(),
|
||||
);
|
||||
assert!(result1.exec_result.unwrap().is_success());
|
||||
assert!(result1.result.unwrap().is_success());
|
||||
|
||||
// They should match because both where called with the same schedule.
|
||||
assert_eq!(result0.gas_consumed, result1.gas_consumed);
|
||||
@@ -2794,7 +2795,7 @@ fn reinstrument_does_charge() {
|
||||
GAS_LIMIT,
|
||||
zero.clone(),
|
||||
);
|
||||
assert!(result2.exec_result.unwrap().is_success());
|
||||
assert!(result2.result.unwrap().is_success());
|
||||
assert!(result2.gas_consumed > result1.gas_consumed);
|
||||
assert_eq!(
|
||||
result2.gas_consumed,
|
||||
|
||||
@@ -27,14 +27,13 @@ mod runtime;
|
||||
use crate::{
|
||||
CodeHash, Schedule, Config,
|
||||
wasm::env_def::FunctionImplProvider,
|
||||
exec::{Ext, Executable, ExportedFunction},
|
||||
exec::{Ext, Executable, ExportedFunction, ExecResult},
|
||||
gas::GasMeter,
|
||||
};
|
||||
use sp_std::prelude::*;
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
use codec::{Encode, Decode};
|
||||
use frame_support::dispatch::DispatchError;
|
||||
use pallet_contracts_primitives::ExecResult;
|
||||
pub use self::runtime::{ReturnCode, Runtime, RuntimeToken};
|
||||
#[cfg(feature = "runtime-benchmarks")]
|
||||
pub use self::code_cache::reinstrument;
|
||||
@@ -246,17 +245,20 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
CodeHash, BalanceOf, Error, Pallet as Contracts,
|
||||
exec::{Ext, StorageKey, AccountIdOf, Executable, SeedOf, BlockNumberOf, RentParams},
|
||||
exec::{
|
||||
Ext, StorageKey, AccountIdOf, Executable, SeedOf, BlockNumberOf,
|
||||
RentParams, ExecError, ErrorOrigin,
|
||||
},
|
||||
gas::GasMeter,
|
||||
tests::{Test, Call, ALICE, BOB},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use sp_core::H256;
|
||||
use sp_core::{Bytes, H256};
|
||||
use hex_literal::hex;
|
||||
use sp_runtime::DispatchError;
|
||||
use frame_support::{assert_ok, dispatch::DispatchResult, weights::Weight};
|
||||
use assert_matches::assert_matches;
|
||||
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags, ExecError, ErrorOrigin};
|
||||
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
const GAS_LIMIT: Weight = 10_000_000_000;
|
||||
@@ -336,7 +338,7 @@ mod tests {
|
||||
Contracts::<Test>::contract_address(&ALICE, &code_hash, salt),
|
||||
ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Vec::new(),
|
||||
data: Bytes(Vec::new()),
|
||||
},
|
||||
0,
|
||||
))
|
||||
@@ -367,7 +369,7 @@ mod tests {
|
||||
});
|
||||
// Assume for now that it was just a plain transfer.
|
||||
// TODO: Add tests for different call outcomes.
|
||||
Ok((ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() }, 0))
|
||||
Ok((ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) }, 0))
|
||||
}
|
||||
fn terminate(
|
||||
&mut self,
|
||||
@@ -946,7 +948,10 @@ mod tests {
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: [0x22; 32].to_vec() });
|
||||
assert_eq!(output, ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Bytes([0x22; 32].to_vec())
|
||||
});
|
||||
}
|
||||
|
||||
/// calls `seal_caller` and compares the result with the constant 42.
|
||||
@@ -1209,7 +1214,7 @@ mod tests {
|
||||
&mut gas_meter,
|
||||
).unwrap();
|
||||
|
||||
let gas_left = Weight::decode(&mut output.data.as_slice()).unwrap();
|
||||
let gas_left = Weight::decode(&mut &*output.data).unwrap();
|
||||
assert!(gas_left < GAS_LIMIT, "gas_left must be less than initial");
|
||||
assert!(gas_left > gas_meter.gas_left(), "gas_left must be greater than final");
|
||||
}
|
||||
@@ -1299,7 +1304,13 @@ mod tests {
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: vec![1, 2, 3, 4] });
|
||||
assert_eq!(
|
||||
output,
|
||||
ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Bytes(vec![1, 2, 3, 4])
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const CODE_TIMESTAMP_NOW: &str = r#"
|
||||
@@ -1526,7 +1537,10 @@ mod tests {
|
||||
output,
|
||||
ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F").to_vec(),
|
||||
data: Bytes(
|
||||
hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F")
|
||||
.to_vec()
|
||||
),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1601,10 +1615,10 @@ mod tests {
|
||||
output,
|
||||
ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: (
|
||||
data: Bytes((
|
||||
hex!("000102030405060708090A0B0C0D0E0F000102030405060708090A0B0C0D0E0F"),
|
||||
42u64,
|
||||
).encode(),
|
||||
).encode()),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -1837,7 +1851,10 @@ mod tests {
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: hex!("445566778899").to_vec() });
|
||||
assert_eq!(output, ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Bytes(hex!("445566778899").to_vec()),
|
||||
});
|
||||
assert!(output.is_success());
|
||||
}
|
||||
|
||||
@@ -1850,7 +1867,10 @@ mod tests {
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::REVERT, data: hex!("5566778899").to_vec() });
|
||||
assert_eq!(output, ExecReturnValue {
|
||||
flags: ReturnFlags::REVERT,
|
||||
data: Bytes(hex!("5566778899").to_vec()),
|
||||
});
|
||||
assert!(!output.is_success());
|
||||
}
|
||||
|
||||
@@ -1962,7 +1982,7 @@ mod tests {
|
||||
MockExt::default(),
|
||||
&mut GasMeter::new(GAS_LIMIT),
|
||||
).unwrap();
|
||||
let rent_params = <RentParams<Test>>::default().encode();
|
||||
let rent_params = Bytes(<RentParams<Test>>::default().encode());
|
||||
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: rent_params });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
use crate::{
|
||||
Config, CodeHash, BalanceOf, Error,
|
||||
exec::{Ext, StorageKey, TopicOf},
|
||||
exec::{Ext, StorageKey, TopicOf, ExecResult, ExecError},
|
||||
gas::{GasMeter, Token, ChargedAmount},
|
||||
wasm::env_def::ConvertibleToWasm,
|
||||
schedule::HostFnWeights,
|
||||
@@ -29,14 +29,14 @@ use frame_support::{dispatch::DispatchError, ensure, traits::Get, weights::Weigh
|
||||
use sp_std::prelude::*;
|
||||
use codec::{Decode, DecodeAll, Encode};
|
||||
use sp_runtime::traits::SaturatedConversion;
|
||||
use sp_core::crypto::UncheckedFrom;
|
||||
use sp_core::{Bytes, crypto::UncheckedFrom};
|
||||
use sp_io::hashing::{
|
||||
keccak_256,
|
||||
blake2_256,
|
||||
blake2_128,
|
||||
sha2_256,
|
||||
};
|
||||
use pallet_contracts_primitives::{ExecResult, ExecReturnValue, ReturnFlags, ExecError};
|
||||
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
|
||||
|
||||
/// Every error that can be returned to a contract when it calls any of the host functions.
|
||||
///
|
||||
@@ -347,19 +347,19 @@ where
|
||||
)?;
|
||||
Ok(ExecReturnValue {
|
||||
flags,
|
||||
data,
|
||||
data: Bytes(data),
|
||||
})
|
||||
},
|
||||
TrapReason::Termination => {
|
||||
Ok(ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Vec::new(),
|
||||
data: Bytes(Vec::new()),
|
||||
})
|
||||
},
|
||||
TrapReason::Restoration => {
|
||||
Ok(ExecReturnValue {
|
||||
flags: ReturnFlags::empty(),
|
||||
data: Vec::new(),
|
||||
data: Bytes(Vec::new()),
|
||||
})
|
||||
},
|
||||
TrapReason::SupervisorError(error) => Err(error)?,
|
||||
@@ -370,7 +370,7 @@ where
|
||||
match sandbox_result {
|
||||
// No traps were generated. Proceed normally.
|
||||
Ok(_) => {
|
||||
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Vec::new() })
|
||||
Ok(ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(Vec::new()) })
|
||||
}
|
||||
// `Error::Module` is returned only if instantiation or linking failed (i.e.
|
||||
// wasm binary tried to import a function that is not provided by the host).
|
||||
@@ -596,7 +596,7 @@ where
|
||||
|
||||
/// Fallible conversion of a `ExecResult` to `ReturnCode`.
|
||||
fn exec_into_return_code(from: ExecResult) -> Result<ReturnCode, DispatchError> {
|
||||
use pallet_contracts_primitives::ErrorOrigin::Callee;
|
||||
use crate::exec::ErrorOrigin::Callee;
|
||||
|
||||
let ExecError { error, origin } = match from {
|
||||
Ok(retval) => return Ok(retval.into()),
|
||||
|
||||
Reference in New Issue
Block a user