Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion cmd/crates/soroban-spec-tools/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ impl Spec {
}
Err(Error::MissingErrorCase(value))
}

/// # Errors
///
/// Might return errors
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![no_std]
use soroban_sdk::{
contract, contracterror, contractimpl, contracttype, symbol_short, vec, Address, Bytes, BytesN,
Duration, Env, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
contract, contracterror, contractimpl, contracttype, panic_with_error, symbol_short, vec,
Address, Bytes, BytesN, Duration, Env, Map, String, Symbol, Timepoint, Val, Vec, I256, U256,
};

#[contract]
Expand Down Expand Up @@ -90,6 +90,14 @@ impl Contract {
}
}

pub fn panic_on_even(env: Env, u32_: u32) -> Result<u32, Error> {
if u32_ % 2 == 1 {
Ok(u32_)
} else {
panic_with_error!(&env, Error::NumberMustBeOdd)
}
}

pub fn u32_(_env: Env, u32_: u32) -> u32 {
u32_
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "test_error_caller"
version = "25.1.0"
authors = ["Stellar Development Foundation <info@stellar.org>"]
license = "Apache-2.0"
edition = "2021"
publish = false

[lib]
crate-type = ["cdylib", "rlib"]
doctest = false

[dependencies]
soroban-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#![no_std]
use soroban_sdk::{
contract, contractclient, contracterror, contractimpl, panic_with_error, Address, Env, IntoVal,
InvokeError, Symbol,
};

/// Mirror of the inner contract's error enum.
/// Must match the error codes defined in custom_types contract.
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
pub enum InnerError {
/// Please provide an odd number
NumberMustBeOdd = 1,
}

/// Minimal client interface for the custom_types contract.
#[contractclient(name = "CustomTypesClient")]
pub trait CustomTypesInterface {
fn u32_fail_on_even(env: Env, u32_: u32) -> Result<u32, InnerError>;
}

#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[repr(u32)]
pub enum OuterError {
/// Caught inner error and remapped
RemappedInner = 10,
/// Uses the same error code as the inner contract
SameCodeAsInner = 1,
}

#[contract]
pub struct ErrorCallerContract;

#[contractimpl]
impl ErrorCallerContract {
/// Try-calls inner's u32_fail_on_even. Catches error, returns OuterError::RemappedInner.
pub fn catch_call(env: Env, inner: Address, u32_: u32) -> Result<u32, OuterError> {
match env.try_invoke_contract::<u32, InvokeError>(
&inner,
&Symbol::new(&env, "u32_fail_on_even"),
(u32_,).into_val(&env),
) {
Ok(Ok(val)) => Ok(val),
_ => Err(OuterError::RemappedInner),
}
}

/// Try-calls inner's u32_fail_on_even. Catches error and returns SameCodeAsInner.
pub fn catch_call_same_code(env: Env, inner: Address, u32_: u32) -> Result<u32, OuterError> {
match env.try_invoke_contract::<u32, InvokeError>(
&inner,
&Symbol::new(&env, "u32_fail_on_even"),
(u32_,).into_val(&env),
) {
Ok(Ok(val)) => Ok(val),
_ => Err(OuterError::SameCodeAsInner),
}
}

/// Try-calls inner via contractclient. Catches error, returns OuterError::RemappedInner.
pub fn catch_call_import(env: Env, inner: Address, u32_: u32) -> Result<u32, OuterError> {
let client = CustomTypesClient::new(&env, &inner);
match client.try_u32_fail_on_even(&u32_) {
Ok(Ok(val)) => Ok(val),
_ => Err(OuterError::RemappedInner),
}
}

/// Non-try call to inner's u32_fail_on_even. If inner fails, propagates as VM trap.
pub fn call(env: Env, inner: Address, u32_: u32) -> Result<u32, OuterError> {
Ok(env.invoke_contract(
&inner,
&Symbol::new(&env, "u32_fail_on_even"),
(u32_,).into_val(&env),
))
}

/// Non-try call to inner via contractclient. If inner fails, propagates as VM trap.
pub fn call_import(env: Env, inner: Address, u32_: u32) -> Result<u32, OuterError> {
let client = CustomTypesClient::new(&env, &inner);
Ok(client.u32_fail_on_even(&u32_))
}

/// Try-calls inner but returns non-Result type. Panics with error if inner fails.
/// Since this function doesn't return Result, the error shouldn't be resolved.
pub fn catch_panic_no_result(env: Env, inner: Address, u32_: u32) -> u32 {
let client = CustomTypesClient::new(&env, &inner);
match client.try_u32_fail_on_even(&u32_) {
Ok(Ok(val)) => val,
_ => panic_with_error!(&env, OuterError::RemappedInner),
}
}
}
1 change: 1 addition & 0 deletions cmd/crates/soroban-test/tests/it/integration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod bindings;
mod constructor;
mod contract;
mod contract_errors;
mod cookbook;
mod custom_types;
mod dotenv;
Expand Down
Loading