Skip to content

Commit 69946de

Browse files
committed
Merge branch 'master' into hc-get-lang-error-from-create-builder
2 parents 9a14e21 + 72f7883 commit 69946de

File tree

27 files changed

+498
-220
lines changed

27 files changed

+498
-220
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## Unreleased
88
- Add E2E testing framework MVP ‒ [#1395](https://github.com/paritytech/ink/pull/1395)
99
- Add E2E tests for `Mapping` functions - [#1492](https://github.com/paritytech/ink/pull/1492)
10+
- Make CallBuilder and CreateBuilder error handling optional - [#1602](https://github.com/paritytech/ink/pull/1602)
11+
- Rename `CallBuilder::fire()` method to `invoke()` - [#1604](https://github.com/paritytech/ink/pull/1604)
12+
13+
### Breaking Changes
14+
With this release there are two breaking changes related to the `CallBuilder` and
15+
`CreateBuilder`.
16+
17+
1. The `invoke()` methods now unwrap the `Result` from `pallet-contracts` under the hood
18+
([#1602](https://github.com/paritytech/ink/pull/1602))
19+
1. The `CallBuilder::fire()` method has been renamed to `invoke()`
20+
([#1604](https://github.com/paritytech/ink/pull/1604))
21+
22+
For (1), if you which to handle the the error use the new `try_` variants of those
23+
methods instead.
1024

1125
## Version 4.0.0-beta
1226

SECURITY.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Reporting a vulnerability
2+
3+
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.
4+
5+
Security vulnerabilities should be reported using [this contact form](https://security-submission.parity.io/).
6+
7+
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.
8+
9+
**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.

crates/e2e/src/client.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use super::{
3333
};
3434
use contract_metadata::ContractMetadata;
3535
use ink_env::Environment;
36+
use ink_primitives::MessageResult;
3637

3738
use sp_runtime::traits::{
3839
IdentifyAccount,
@@ -124,7 +125,7 @@ pub struct CallResult<C: subxt::Config, E: Environment, V> {
124125
pub events: ExtrinsicEvents<C>,
125126
/// Contains the result of decoding the return value of the called
126127
/// function.
127-
pub value: Result<V, scale::Error>,
128+
pub value: Result<MessageResult<V>, scale::Error>,
128129
/// Returns the bytes of the encoded dry-run return value.
129130
pub data: Vec<u8>,
130131
}
@@ -139,12 +140,19 @@ where
139140
/// Panics if the value could not be decoded. The raw bytes can be accessed
140141
/// via [`return_data`].
141142
pub fn return_value(self) -> V {
142-
self.value.unwrap_or_else(|err| {
143-
panic!(
144-
"decoding dry run result to ink! message return type failed: {}",
145-
err
146-
)
147-
})
143+
self.value
144+
.unwrap_or_else(|env_err| {
145+
panic!(
146+
"Decoding dry run result to ink! message return type failed: {}",
147+
env_err
148+
)
149+
})
150+
.unwrap_or_else(|lang_err| {
151+
panic!(
152+
"Encountered a `LangError` while decoding dry run result to ink! message: {:?}",
153+
lang_err
154+
)
155+
})
148156
}
149157

150158
/// Returns true if the specified event was triggered by the call.
@@ -655,7 +663,7 @@ where
655663
}
656664

657665
let bytes = &dry_run.result.as_ref().unwrap().data;
658-
let value: Result<RetType, scale::Error> =
666+
let value: Result<MessageResult<RetType>, scale::Error> =
659667
scale::Decode::decode(&mut bytes.as_ref());
660668

661669
Ok(CallResult {

crates/env/src/api.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ where
268268
/// - If the called contract execution has trapped.
269269
/// - If the called contract ran out of gas upon execution.
270270
/// - If the returned value failed to decode properly.
271-
pub fn invoke_contract<E, Args, R>(params: &CallParams<E, Call<E>, Args, R>) -> Result<R>
271+
pub fn invoke_contract<E, Args, R>(
272+
params: &CallParams<E, Call<E>, Args, R>,
273+
) -> Result<ink_primitives::MessageResult<R>>
272274
where
273275
E: Environment,
274276
Args: scale::Encode,

crates/env/src/backend.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ pub trait TypedEnvBackend: EnvBackend {
414414
fn invoke_contract<E, Args, R>(
415415
&mut self,
416416
call_data: &CallParams<E, Call<E>, Args, R>,
417-
) -> Result<R>
417+
) -> Result<ink_primitives::MessageResult<R>>
418418
where
419419
E: Environment,
420420
Args: scale::Encode,

crates/env/src/call/call_builder.rs

Lines changed: 155 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,31 @@ where
109109
/// Invokes the contract with the given built-up call parameters.
110110
///
111111
/// Returns the result of the contract execution.
112-
pub fn invoke(&self) -> Result<R, crate::Error> {
112+
///
113+
/// # Panics
114+
///
115+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
116+
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
117+
/// use the [`try_invoke`][`CallParams::try_invoke`] method instead.
118+
pub fn invoke(&self) -> R {
119+
crate::invoke_contract(self)
120+
.unwrap_or_else(|env_error| {
121+
panic!("Cross-contract call failed with {:?}", env_error)
122+
})
123+
.unwrap_or_else(|lang_error| {
124+
panic!("Cross-contract call failed with {:?}", lang_error)
125+
})
126+
}
127+
128+
/// Invokes the contract with the given built-up call parameters.
129+
///
130+
/// Returns the result of the contract execution.
131+
///
132+
/// # Note
133+
///
134+
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
135+
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
136+
pub fn try_invoke(&self) -> Result<ink_primitives::MessageResult<R>, crate::Error> {
113137
crate::invoke_contract(self)
114138
}
115139
}
@@ -120,11 +144,29 @@ where
120144
Args: scale::Encode,
121145
R: scale::Decode,
122146
{
123-
/// Invokes the contract via delegated call with the given
124-
/// built-up call parameters.
147+
/// Invoke the contract using Delegate Call semantics with the given built-up call parameters.
125148
///
126149
/// Returns the result of the contract execution.
127-
pub fn invoke(&self) -> Result<R, crate::Error> {
150+
///
151+
/// # Panics
152+
///
153+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]. If you want to
154+
/// handle those use the [`try_invoke`][`CallParams::try_invoke`] method instead.
155+
pub fn invoke(&self) -> R {
156+
crate::invoke_contract_delegate(self).unwrap_or_else(|env_error| {
157+
panic!("Cross-contract call failed with {:?}", env_error)
158+
})
159+
}
160+
161+
/// Invoke the contract using Delegate Call semantics with the given built-up call parameters.
162+
///
163+
/// Returns the result of the contract execution.
164+
///
165+
/// # Note
166+
///
167+
/// On failure this returns an [`ink::env::Error`][`crate::Error`] which can be handled by the
168+
/// caller.
169+
pub fn try_invoke(&self) -> Result<R, crate::Error> {
128170
crate::invoke_contract_delegate(self)
129171
}
130172
}
@@ -172,8 +214,7 @@ where
172214
/// .push_arg(&[0x10u8; 32])
173215
/// )
174216
/// .returns::<()>()
175-
/// .fire()
176-
/// .unwrap();
217+
/// .invoke();
177218
/// ```
178219
///
179220
/// ## Example 2: With Return Value
@@ -208,8 +249,7 @@ where
208249
/// .push_arg(&[0x10u8; 32])
209250
/// )
210251
/// .returns::<i32>()
211-
/// .fire()
212-
/// .unwrap();
252+
/// .invoke();
213253
/// ```
214254
///
215255
/// ## Example 3: Delegate call
@@ -236,8 +276,47 @@ where
236276
/// .push_arg(&[0x10u8; 32])
237277
/// )
238278
/// .returns::<i32>()
239-
/// .fire()
240-
/// .unwrap();
279+
/// .invoke();
280+
/// ```
281+
///
282+
/// # Handling `LangError`s
283+
///
284+
/// It is also important to note that there are certain types of errors which can happen during
285+
/// cross-contract calls which can be handled know as [`LangError`][`ink_primitives::LangError`].
286+
///
287+
/// If you want to handle these errors use the [`CallBuilder::try_invoke`] methods instead of the
288+
/// [`CallBuilder::invoke`] ones.
289+
///
290+
/// **Note:** The shown examples panic because there is currently no cross-calling
291+
/// support in the off-chain testing environment. However, this code
292+
/// should work fine in on-chain environments.
293+
///
294+
/// ## Example: Handling a `LangError`
295+
///
296+
/// ```should_panic
297+
/// # use ::ink_env::{
298+
/// # Environment,
299+
/// # DefaultEnvironment,
300+
/// # call::{build_call, Selector, ExecutionInput}
301+
/// # };
302+
/// # use ink_env::call::Call;
303+
/// # type AccountId = <DefaultEnvironment as Environment>::AccountId;
304+
/// # type Balance = <DefaultEnvironment as Environment>::Balance;
305+
/// let call_result = build_call::<DefaultEnvironment>()
306+
/// .call_type(
307+
/// Call::new()
308+
/// .callee(AccountId::from([0x42; 32]))
309+
/// .gas_limit(5000)
310+
/// .transferred_value(10),
311+
/// )
312+
/// .try_invoke()
313+
/// .expect("Got an error from the Contract's pallet.");
314+
///
315+
/// match call_result {
316+
/// Ok(_) => unimplemented!(),
317+
/// Err(e @ ink_primitives::LangError::CouldNotReadInput) => unimplemented!(),
318+
/// Err(_) => unimplemented!(),
319+
/// }
241320
/// ```
242321
#[allow(clippy::type_complexity)]
243322
pub fn build_call<E>() -> CallBuilder<
@@ -597,9 +676,25 @@ where
597676
E: Environment,
598677
{
599678
/// Invokes the cross-chain function call.
600-
pub fn fire(self) -> Result<(), Error> {
679+
///
680+
/// # Panics
681+
///
682+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
683+
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
684+
/// use the [`try_invoke`][`CallBuilder::try_invoke`] method instead.
685+
pub fn invoke(self) {
601686
self.params().invoke()
602687
}
688+
689+
/// Invokes the cross-chain function call.
690+
///
691+
/// # Note
692+
///
693+
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
694+
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
695+
pub fn try_invoke(self) -> Result<ink_primitives::MessageResult<()>, Error> {
696+
self.params().try_invoke()
697+
}
603698
}
604699

605700
impl<E>
@@ -612,10 +707,24 @@ impl<E>
612707
where
613708
E: Environment,
614709
{
615-
/// Invokes the cross-chain function call.
616-
pub fn fire(self) -> Result<(), Error> {
710+
/// Invokes the cross-chain function call using Delegate Call semantics.
711+
///
712+
/// # Panics
713+
///
714+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]
715+
/// If you want to handle those use the [`try_invoke`][`CallBuilder::try_invoke`] method instead.
716+
pub fn invoke(self) {
617717
self.params().invoke()
618718
}
719+
720+
/// Invokes the cross-chain function call using Delegate Call semantics.
721+
///
722+
/// # Note
723+
///
724+
/// On failure this an [`ink::env::Error`][`crate::Error`] which can be handled by the caller.
725+
pub fn try_invoke(self) -> Result<(), Error> {
726+
self.params().try_invoke()
727+
}
619728
}
620729

621730
impl<E, Args, R>
@@ -626,9 +735,25 @@ where
626735
R: scale::Decode,
627736
{
628737
/// Invokes the cross-chain function call and returns the result.
629-
pub fn fire(self) -> Result<R, Error> {
738+
///
739+
/// # Panics
740+
///
741+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`] or an
742+
/// [`ink::primitives::LangError`][`ink_primitives::LangError`]. If you want to handle those
743+
/// use the [`try_invoke`][`CallBuilder::try_invoke`] method instead.
744+
pub fn invoke(self) -> R {
630745
self.params().invoke()
631746
}
747+
748+
/// Invokes the cross-chain function call and returns the result.
749+
///
750+
/// # Note
751+
///
752+
/// On failure this returns an outer [`ink::env::Error`][`crate::Error`] or inner
753+
/// [`ink_primitives::LangError`], both of which can be handled by the caller.
754+
pub fn try_invoke(self) -> Result<ink_primitives::MessageResult<R>, Error> {
755+
self.params().try_invoke()
756+
}
632757
}
633758

634759
impl<E, Args, R>
@@ -638,8 +763,22 @@ where
638763
Args: scale::Encode,
639764
R: scale::Decode,
640765
{
641-
/// Invokes the cross-chain function call and returns the result.
642-
pub fn fire(self) -> Result<R, Error> {
766+
/// Invokes the cross-chain function call using Delegate Call semantics and returns the result.
767+
///
768+
/// # Panics
769+
///
770+
/// This method panics if it encounters an [`ink::env::Error`][`crate::Error`]
771+
/// If you want to handle those use the [`try_invoke`][`CallBuilder::try_invoke`] method instead.
772+
pub fn invoke(self) -> R {
643773
self.params().invoke()
644774
}
775+
776+
/// Invokes the cross-chain function call using Delegate Call semantics and returns the result.
777+
///
778+
/// # Note
779+
///
780+
/// On failure this an [`ink::env::Error`][`crate::Error`] which can be handled by the caller.
781+
pub fn try_invoke(self) -> Result<R, Error> {
782+
self.params().try_invoke()
783+
}
645784
}

0 commit comments

Comments
 (0)