diff --git a/Cargo.lock b/Cargo.lock index ee655c5..bfc9981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3473,6 +3473,7 @@ dependencies = [ "frame-system", "log", "pallet-assets", + "pallet-nfts 31.0.0", "parity-scale-codec", "pop-chain-extension", "scale-info", diff --git a/crates/pop-drink/src/error.rs b/crates/pop-drink/src/error.rs index 319e3c8..dd43094 100644 --- a/crates/pop-drink/src/error.rs +++ b/crates/pop-drink/src/error.rs @@ -22,17 +22,18 @@ fn decode(data: &[u8]) -> T { /// /// # Examples /// -/// To assert the `StatusCode` returned by a contract method that uses Pop API, you simply use the provided `assert_err!` macro. +/// To assert the `StatusCode` returned by a contract method that uses Pop API, you simply use the +/// provided `assert_err!` macro. /// /// ```rs /// // Required imports to test the custom error. /// use drink::{ assert_err, devnet::error::{ v0::Error, Arithmetic, ArithmeticError::Overflow }}; /// -/// // Call a contract method named "hello_world" that returns `StatusCode`. +/// // Call a contract method named "hello_world" that throws `StatusCode`. /// let result = call::(session, "hello_world", vec![], None); /// -/// // Using macro to test the returned error. -/// assert_err!(result, Error::Api(Arithmetic(Overflow))); +/// // Asserts that the call fails because of an arithmetic operation error. +/// assert_err!(result, Error::Raw(Arithmetic(Overflow))); /// ``` #[macro_export] macro_rules! assert_err { @@ -84,155 +85,177 @@ where } } -/// Runtime error for efficiently testing both runtime module errors and API errors. -/// It is designed for use with the `assert_err!` macro. +/// Error type for testing why a runtime call fails. /// /// # Generic Parameters /// -/// - `ModuleError` - Error type of the runtime modules. [Reference](https://paritytech.github.io/polkadot-sdk/master/solochain_template_runtime/enum.Error.html). -/// - `ApiError` - Error type of the API, which depends on version. [Reference](https://github.com/r0gue-io/pop-node/tree/main/pop-api). -/// - `MODULE_INDEX` - Index of the variant `Error::Module`. This is based on the index of [`ApiError::Module`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L38). +/// - [`RuntimeCallError`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L30) +/// - Reason why a runtime call fails. (.e.g, arithmetic operation errors) +/// - [`ModuleError`](https://paritytech.github.io/polkadot-sdk/master/solochain_template_runtime/enum.Error.html) +/// - Refers to specific reasons a runtime call fails, originating from the runtime modules. +/// - [`MODULE_INDEX`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L38) +/// - Index of the variant `Error::Module`. /// /// # Examples /// -/// ### Runtime module errors +/// ### Runtime call errors /// -/// - Import types to construct runtime module errors: +/// - Import types to construct runtime call errors: /// /// ```rs -/// use drink::devnet::{ -/// Assets, -/// AssetsError::AssetNotLive, -/// Balances::BelowMinimum, -/// BalancesError::BelowMinimum +/// use drink::devnet::v0::{ +/// Arithmetic, +/// ArithmeticError::Overflow, +/// BadOrigin /// }; /// ``` /// -/// - Construct a runtime module error [`Assets(AssetNotLive)`](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/pallet/enum.Error.html#variant.AssetNotLive): +/// - Runtime call error [`Arithmetic(Overflow)`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L55): /// /// ```rs -/// Error::Module(Assets(AssetNotLive)) +/// Error::Raw(Arithmetic(Overflow)) /// ``` /// -/// - Construct a runtime module error [`Balances(InsufficientBalance)`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/enum.Error.html#variant.InsufficientBalance): +/// - Runtime call error [`BadOrigin`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L36C4-L36C18): /// /// ```rs -/// Error::Module(Balances(InsufficientBalance)) +/// Error::Raw(BadOrigin) /// ``` /// -/// ### API errors +/// ### Runtime module errors /// -/// - Import types to construct API errors: +/// - Import types to construct runtime module errors: /// /// ```rs -/// use drink::devnet::v0::{ -/// Arithmetic, -/// ArithmeticError::Overflow, -/// BadOrigin +/// use drink::devnet::{ +/// Assets, +/// AssetsError::AssetNotLive, +/// Balances::BelowMinimum, +/// BalancesError::BelowMinimum /// }; /// ``` /// -/// - API error [`Arithmetic(Overflow)`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L55): +/// - Construct a runtime module error [`Assets(AssetNotLive)`](https://paritytech.github.io/polkadot-sdk/master/pallet_assets/pallet/enum.Error.html#variant.AssetNotLive): /// /// ```rs -/// Error::Api(Arithmetic(Overflow)) +/// Error::Module(Assets(AssetNotLive)) /// ``` /// -/// - API error [`BadOrigin`](https://github.com/r0gue-io/pop-node/blob/main/primitives/src/lib.rs#L36C4-L36C18): +/// - Construct a runtime module error [`Balances(InsufficientBalance)`](https://docs.rs/pallet-balances/latest/pallet_balances/pallet/enum.Error.html#variant.InsufficientBalance): /// /// ```rs -/// Error::Api(BadOrigin) +/// Error::Module(Balances(InsufficientBalance)) /// ``` + #[derive(Encode, Decode, Debug)] -pub enum Error +pub enum Error where + RuntimeCallError: Decode + Encode + Debug + From + Into, ModuleError: Decode + Encode + Debug, - ApiError: Decode + Encode + Debug + From + Into, { - /// Error type of the runtime modules. [Reference](https://paritytech.github.io/polkadot-sdk/master/solochain_template_runtime/enum.Error.html). + /// Reason why a runtime call fails. [Reference](https://github.com/r0gue-io/pop-node/blob/52fb7f06a89955d462900e33d2b9c9170c4534a0/primitives/src/lib.rs#L30). + Raw(RuntimeCallError), + /// [Module error](https://paritytech.github.io/polkadot-sdk/master/solochain_template_runtime/enum.Error.html) refers to specific reasons a runtime call fails, originating from the runtime modules. Module(ModuleError), - /// Every [`ApiError`](https://github.com/r0gue-io/pop-node/blob/52fb7f06a89955d462900e33d2b9c9170c4534a0/primitives/src/lib.rs#L30). - Api(ApiError), } -impl From> - for u32 +impl + From> for u32 where + RuntimeCallError: Decode + Encode + Debug + From + Into, ModuleError: Decode + Encode + Debug, - ApiError: Decode + Encode + Debug + From + Into, { - /// Converts an `Error` into a numerical value of `ApiError`. + /// Converts an `Error` to a `u32` number. /// /// This conversion is necessary for comparing `Error` instances with other types. // Compared types must implement `Into`, as `Error` does not implement `Eq`. // Use this function to obtain a numerical representation of the error for comparison or // further processing. - fn from(error: Error) -> Self { + fn from(error: Error) -> Self { match error { + Error::Raw(error) => decode::(&error.encode()), Error::Module(error) => { let mut encoded = error.encode(); encoded.insert(0, MODULE_INDEX); encoded.resize(4, 0); - decode::(&encoded) + decode::(&encoded) }, - Error::Api(error) => decode::(&error.encode()), } .into() } } -impl From - for Error +impl From + for Error where + RuntimeCallError: Decode + Encode + Debug + From + Into, ModuleError: Decode + Encode + Debug, - ApiError: Decode + Encode + Debug + From + Into, { - /// Converts a numerical value of `ApiError` into an `Error`. + /// Converts a numerical value `u32` into an `Error`. /// /// This is used to reconstruct and display an `Error` from its numerical representation /// when an error is thrown. fn from(value: u32) -> Self { - let error = ApiError::from(value); + let error = RuntimeCallError::from(value); let encoded = error.encode(); if encoded[0] == MODULE_INDEX { let (index, module_error) = (encoded[1], &encoded[2..]); let data = vec![vec![index], module_error.to_vec()].concat(); return Error::Module(decode(&data)); } - Error::Api(error) + Error::Raw(error) } } #[cfg(test)] mod test { - use pop_api::primitives::v0::Error as ApiError; + use pop_api::primitives::v0::Error as RuntimeCallError; use crate::error::{AssetsError::*, BalancesError::*, *}; - fn test_cases() -> Vec<(Error, ApiError)> { + fn test_cases() -> Vec<(Error, RuntimeCallError)> + { use frame_support::traits::PalletInfoAccess; use pop_api::primitives::{ArithmeticError::*, TokenError::*}; use crate::mock::RuntimeError::*; vec![ - (Error::Api(ApiError::BadOrigin), ApiError::BadOrigin), - (Error::Api(ApiError::Token(BelowMinimum)), ApiError::Token(BelowMinimum)), - (Error::Api(ApiError::Arithmetic(Overflow)), ApiError::Arithmetic(Overflow)), + (Error::Raw(RuntimeCallError::BadOrigin), RuntimeCallError::BadOrigin), + ( + Error::Raw(RuntimeCallError::Token(BelowMinimum)), + RuntimeCallError::Token(BelowMinimum), + ), + ( + Error::Raw(RuntimeCallError::Arithmetic(Overflow)), + RuntimeCallError::Arithmetic(Overflow), + ), ( Error::Module(Assets(BalanceLow)), - ApiError::Module { index: crate::mock::Assets::index() as u8, error: [0, 0] }, + RuntimeCallError::Module { + index: crate::mock::Assets::index() as u8, + error: [0, 0], + }, ), ( Error::Module(Assets(NoAccount)), - ApiError::Module { index: crate::mock::Assets::index() as u8, error: [1, 0] }, + RuntimeCallError::Module { + index: crate::mock::Assets::index() as u8, + error: [1, 0], + }, ), ( Error::Module(Balances(VestingBalance)), - ApiError::Module { index: crate::mock::Balances::index() as u8, error: [0, 0] }, + RuntimeCallError::Module { + index: crate::mock::Balances::index() as u8, + error: [0, 0], + }, ), ( Error::Module(Balances(LiquidityRestrictions)), - ApiError::Module { index: crate::mock::Balances::index() as u8, error: [1, 0] }, + RuntimeCallError::Module { + index: crate::mock::Balances::index() as u8, + error: [1, 0], + }, ), ] } diff --git a/crates/pop-drink/src/lib.rs b/crates/pop-drink/src/lib.rs index 2e27654..ab24098 100644 --- a/crates/pop-drink/src/lib.rs +++ b/crates/pop-drink/src/lib.rs @@ -24,10 +24,11 @@ pub mod devnet { /// A collection of error types from the `v0` module used for smart contract testing in the /// `devnet` environment. pub mod v0 { - pub use pop_api::primitives::v0::{Error as ApiError, *}; + pub use pop_api::primitives::v0::{Error as RuntimeCallError, *}; /// Error type for testing contracts using the API V0. - pub type Error = crate::error::Error; + pub type Error = + crate::error::Error; } }