Skip to content

Commit

Permalink
Merge branch 'master' into hc-get-lang-error-from-create-builder
Browse files Browse the repository at this point in the history
  • Loading branch information
ascjones committed Jan 20, 2023
2 parents 9a14e21 + a83c937 commit 09af6a2
Show file tree
Hide file tree
Showing 27 changed files with 460 additions and 333 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
- Add E2E testing framework MVP ‒ [#1395](https://github.com/paritytech/ink/pull/1395)
- Add E2E tests for `Mapping` functions - [#1492](https://github.com/paritytech/ink/pull/1492)
- Make CallBuilder and CreateBuilder error handling optional - [#1602](https://github.com/paritytech/ink/pull/1602)

### Breaking Changes
With the addition of [#1602](https://github.com/paritytech/ink/pull/1602),
the `CallBuilder::fire()`, `CallParams::invoke()`, and `CreateBuilder::instantiate()`
methods now unwrap the `Result` from `pallet-contracts` under the hood.

If you wish to handle the error use the new `try_` variants of those methods instead.

## Version 4.0.0-beta

Expand Down
9 changes: 9 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Reporting a vulnerability

If you find something that can be treated as a security vulnerability, please do not use the issue tracker or discuss it in the public forum/channels, as it can cause more damage rather than giving real help to the ecosystem.

Security vulnerabilities should be reported using [this contact form](https://security-submission.parity.io/).

If you think that your report might be eligible for the Bug Bounty Program, please mark this during the submission. Please check up-to-date [Parity Bug Bounty Program rules](https://www.parity.io/bug-bounty) for more information about our Bug Bounty Program.

**Warning:** This is an unified `SECURITY.md` file for the Paritytech GitHub Organization. The presence of this file does not mean that this repository is covered by the Bug Bounty program. Please always check the Bug Bounty Program scope for the information.
24 changes: 16 additions & 8 deletions crates/e2e/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use super::{
};
use contract_metadata::ContractMetadata;
use ink_env::Environment;
use ink_primitives::MessageResult;

use sp_runtime::traits::{
IdentifyAccount,
Expand Down Expand Up @@ -124,7 +125,7 @@ pub struct CallResult<C: subxt::Config, E: Environment, V> {
pub events: ExtrinsicEvents<C>,
/// Contains the result of decoding the return value of the called
/// function.
pub value: Result<V, scale::Error>,
pub value: Result<MessageResult<V>, scale::Error>,
/// Returns the bytes of the encoded dry-run return value.
pub data: Vec<u8>,
}
Expand All @@ -139,12 +140,19 @@ where
/// Panics if the value could not be decoded. The raw bytes can be accessed
/// via [`return_data`].
pub fn return_value(self) -> V {
self.value.unwrap_or_else(|err| {
panic!(
"decoding dry run result to ink! message return type failed: {}",
err
)
})
self.value
.unwrap_or_else(|env_err| {
panic!(
"Decoding dry run result to ink! message return type failed: {}",
env_err
)
})
.unwrap_or_else(|lang_err| {
panic!(
"Encountered a `LangError` while decoding dry run result to ink! message: {:?}",
lang_err
)
})
}

/// Returns true if the specified event was triggered by the call.
Expand Down Expand Up @@ -655,7 +663,7 @@ where
}

let bytes = &dry_run.result.as_ref().unwrap().data;
let value: Result<RetType, scale::Error> =
let value: Result<MessageResult<RetType>, scale::Error> =
scale::Decode::decode(&mut bytes.as_ref());

Ok(CallResult {
Expand Down
4 changes: 3 additions & 1 deletion crates/env/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,9 @@ where
/// - If the called contract execution has trapped.
/// - If the called contract ran out of gas upon execution.
/// - If the returned value failed to decode properly.
pub fn invoke_contract<E, Args, R>(params: &CallParams<E, Call<E>, Args, R>) -> Result<R>
pub fn invoke_contract<E, Args, R>(
params: &CallParams<E, Call<E>, Args, R>,
) -> Result<ink_primitives::MessageResult<R>>
where
E: Environment,
Args: scale::Encode,
Expand Down
2 changes: 1 addition & 1 deletion crates/env/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ pub trait TypedEnvBackend: EnvBackend {
fn invoke_contract<E, Args, R>(
&mut self,
call_data: &CallParams<E, Call<E>, Args, R>,
) -> Result<R>
) -> Result<ink_primitives::MessageResult<R>>
where
E: Environment,
Args: scale::Encode,
Expand Down
171 changes: 155 additions & 16 deletions crates/env/src/call/call_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,31 @@ where
/// Invokes the contract with the given built-up call parameters.
///
/// Returns the result of the contract execution.
pub fn invoke(&self) -> Result<R, crate::Error> {
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
/// use the [`try_invoke`][`CallParams::try_invoke`] method instead.
pub fn invoke(&self) -> R {
crate::invoke_contract(self)
.unwrap_or_else(|env_error| {
panic!("Cross-contract call failed with {:?}", env_error)
})
.unwrap_or_else(|lang_error| {
panic!("Cross-contract call failed with {:?}", lang_error)
})
}

/// Invokes the contract with the given built-up call parameters.
///
/// Returns the result of the contract execution.
///
/// # Note
///
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
pub fn try_invoke(&self) -> Result<ink_primitives::MessageResult<R>, crate::Error> {
crate::invoke_contract(self)
}
}
Expand All @@ -120,11 +144,29 @@ where
Args: scale::Encode,
R: scale::Decode,
{
/// Invokes the contract via delegated call with the given
/// built-up call parameters.
/// Invoke the contract using Delegate Call semantics with the given built-up call parameters.
///
/// Returns the result of the contract execution.
pub fn invoke(&self) -> Result<R, crate::Error> {
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] If you want to
/// handle those use the [`try_invoke`][`CallParams::try_invoke`] method instead.
pub fn invoke(&self) -> R {
crate::invoke_contract_delegate(self).unwrap_or_else(|env_error| {
panic!("Cross-contract call failed with {:?}", env_error)
})
}

/// Invoke the contract using Delegate Call semantics with the given built-up call parameters.
///
/// Returns the result of the contract execution.
///
/// # Note
///
/// On failure this returns an [`ink::env::Error`][`crate::Error`] which can be handled by the
/// caller.
pub fn try_invoke(&self) -> Result<R, crate::Error> {
crate::invoke_contract_delegate(self)
}
}
Expand Down Expand Up @@ -172,8 +214,7 @@ where
/// .push_arg(&[0x10u8; 32])
/// )
/// .returns::<()>()
/// .fire()
/// .unwrap();
/// .fire();
/// ```
///
/// ## Example 2: With Return Value
Expand Down Expand Up @@ -208,8 +249,7 @@ where
/// .push_arg(&[0x10u8; 32])
/// )
/// .returns::<i32>()
/// .fire()
/// .unwrap();
/// .fire();
/// ```
///
/// ## Example 3: Delegate call
Expand All @@ -236,8 +276,47 @@ where
/// .push_arg(&[0x10u8; 32])
/// )
/// .returns::<i32>()
/// .fire()
/// .unwrap();
/// .fire();
/// ```
///
/// # Handling `LangError`s
///
/// It is also important to note that there are certain types of errors which can happen during
/// cross-contract calls which can be handled know as [`LangError`][`ink_primitives::LangError`].
///
/// If you want to handle these errors use the [`CallBuilder::try_fire`] methods instead of the
/// [`CallBuilder::fire`] ones.
///
/// **Note:** The shown examples panic because there is currently no cross-calling
/// support in the off-chain testing environment. However, this code
/// should work fine in on-chain environments.
///
/// ## Example: Handling a `LangError`
///
/// ```should_panic
/// # use ::ink_env::{
/// # Environment,
/// # DefaultEnvironment,
/// # call::{build_call, Selector, ExecutionInput}
/// # };
/// # use ink_env::call::Call;
/// # type AccountId = <DefaultEnvironment as Environment>::AccountId;
/// # type Balance = <DefaultEnvironment as Environment>::Balance;
/// let call_result = build_call::<DefaultEnvironment>()
/// .call_type(
/// Call::new()
/// .callee(AccountId::from([0x42; 32]))
/// .gas_limit(5000)
/// .transferred_value(10),
/// )
/// .try_fire()
/// .expect("Got an error from the Contract's pallet.");
///
/// match call_result {
/// Ok(_) => unimplemented!(),
/// Err(e @ ink_primitives::LangError::CouldNotReadInput) => unimplemented!(),
/// Err(_) => unimplemented!(),
/// }
/// ```
#[allow(clippy::type_complexity)]
pub fn build_call<E>() -> CallBuilder<
Expand Down Expand Up @@ -597,9 +676,25 @@ where
E: Environment,
{
/// Invokes the cross-chain function call.
pub fn fire(self) -> Result<(), Error> {
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
/// use the [`try_fire`][`CallBuilder::try_fire`] method instead.
pub fn fire(self) {
self.params().invoke()
}

/// Invokes the cross-chain function call.
///
/// # Note
///
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
pub fn try_fire(self) -> Result<ink_primitives::MessageResult<()>, Error> {
self.params().try_invoke()
}
}

impl<E>
Expand All @@ -612,10 +707,24 @@ impl<E>
where
E: Environment,
{
/// Invokes the cross-chain function call.
pub fn fire(self) -> Result<(), Error> {
/// Invokes the cross-chain function call using Delegate Call semantics.
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]
/// If you want to handle those use the [`try_fire`][`CallBuilder::try_fire`] method instead.
pub fn fire(self) {
self.params().invoke()
}

/// Invokes the cross-chain function call using Delegate Call semantics.
///
/// # Note
///
/// On failure this an [`ink::env::Error`][`crate::Error`] which can be handled by the caller.
pub fn try_fire(self) -> Result<(), Error> {
self.params().try_invoke()
}
}

impl<E, Args, R>
Expand All @@ -626,9 +735,25 @@ where
R: scale::Decode,
{
/// Invokes the cross-chain function call and returns the result.
pub fn fire(self) -> Result<R, Error> {
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
/// use the [`try_fire`][`CallBuilder::try_fire`] method instead.
pub fn fire(self) -> R {
self.params().invoke()
}

/// Invokes the cross-chain function call and returns the result.
///
/// # Note
///
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
pub fn try_fire(self) -> Result<ink_primitives::MessageResult<R>, Error> {
self.params().try_invoke()
}
}

impl<E, Args, R>
Expand All @@ -638,8 +763,22 @@ where
Args: scale::Encode,
R: scale::Decode,
{
/// Invokes the cross-chain function call and returns the result.
pub fn fire(self) -> Result<R, Error> {
/// Invokes the cross-chain function call using Delegate Call semantics and returns the result.
///
/// # Panics
///
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]
/// If you want to handle those use the [`try_fire`][`CallBuilder::try_fire`] method instead.
pub fn fire(self) -> R {
self.params().invoke()
}

/// Invokes the cross-chain function call using Delegate Call semantics and returns the result.
///
/// # Note
///
/// On failure this an [`ink::env::Error`][`crate::Error`] which can be handled by the caller.
pub fn try_fire(self) -> Result<R, Error> {
self.params().try_invoke()
}
}
Loading

0 comments on commit 09af6a2

Please sign in to comment.