From fa8f61576f49dc529cac5a0fe3319da28b2d4ffc Mon Sep 17 00:00:00 2001 From: Leigh McCulloch <351529+leighmcculloch@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:38:53 +1000 Subject: [PATCH 1/3] Remove backtrace (#1464) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### What Moved backtrace in the Host's DebugInfo behind a new feature. ### Why The backtrace output is included in the Debug formatting of errors when testutils are enabled, but the trace has not turned out to be that useful in contract tests written with the SDK. When an error occurs in a contract test the output includes two long stack traces. The first is the one provided by backtrace. The second is one provided by the Rust test harness. Both are very similar and contain approximately the same information. The Rust test harness' trace is actually a little easier to read because it's not quite so verbose. Here's a before and after of what a test failing looks like before and after this change: #### Before ``` HostError: Error(Auth, InvalidAction) Event log (newest first): 0: [Diagnostic Event] topics:[error, Error(Auth, InvalidAction)], data:"escalating error to panic" 1: [Diagnostic Event] topics:[error, Error(Auth, InvalidAction)], data:["contract call failed", exec, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4]] 2: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:"caught error from function" 3: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:"escalating error to panic" 4: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:["Unauthorized function call for address", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4] 5: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000003), exec], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4 6: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000005), __constructor], data:Void 7: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000004), __constructor], data:Void 8: [Diagnostic Event] topics:[log], data:["holder_2", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM] 9: [Diagnostic Event] topics:[log], data:["holder_1", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4] 10: [Diagnostic Event] topics:[log], data:["test_id", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M] 11: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000003), __constructor], data:Void 12: [Diagnostic Event] topics:[log], data:["auth_id", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4] 13: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4, topics:[fn_return, init], data:Void 14: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000002), init], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 2] 15: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000002), __constructor], data:Void 16: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), __constructor], data:Void Backtrace (newest first): 0: backtrace::backtrace::libunwind::trace at /Users/leighmcculloch/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/libunwind.rs:116:5 backtrace::backtrace::trace_unsynchronized at /Users/leighmcculloch/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:66:5 1: backtrace::backtrace::trace at /Users/leighmcculloch/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:53:14 2: backtrace::capture::Backtrace::create at /Users/leighmcculloch/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:292:9 3: backtrace::capture::Backtrace::new_unresolved at /Users/leighmcculloch/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:287:9 4: soroban_env_host::host::error::::maybe_get_debug_info::{{closure}} at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host/error.rs:299:37 5: soroban_env_host::budget::Budget::with_shadow_mode at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/budget.rs:1039:21 6: soroban_env_host::host::Host::with_debug_mode at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host.rs:650:24 7: soroban_env_host::host::error::::maybe_get_debug_info at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host/error.rs:296:13 8: soroban_env_host::host::error::::error::{{closure}} at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host/error.rs:280:23 9: soroban_env_host::budget::Budget::with_shadow_mode at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/budget.rs:1039:21 10: soroban_env_host::host::Host::with_debug_mode at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host.rs:650:24 11: soroban_env_host::host::error::::error at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host/error.rs:267:9 12: ::escalate_error_to_panic at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host.rs:838:26 13: soroban_sdk::env::internal::reject_err::{{closure}} at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:23 14: core::result::Result::map_err at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27 15: soroban_sdk::env::internal::reject_err at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:9 16: ::call at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:1796:13 17: soroban_sdk::env::Env::invoke_contract at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:379:18 18: auth::tests::TestContractClient::exec at /Users/leighmcculloch/Code/talk-stellar-meridian24-testing/auth/src/tests.rs:17:1 19: auth::tests::unit_test at /Users/leighmcculloch/Code/talk-stellar-meridian24-testing/auth/src/tests.rs:61:5 20: auth::tests::unit_test::{{closure}} at /Users/leighmcculloch/Code/talk-stellar-meridian24-testing/auth/src/tests.rs:35:15 21: core::ops::function::FnOnce::call_once at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5 stack backtrace: 0: rust_begin_unwind at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5 1: core::panicking::panic_fmt at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14 2: ::escalate_error_to_panic at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-env-230c62c6b1f3d3f1/75b7821/soroban-env-host/src/host.rs:839:9 3: soroban_sdk::env::internal::reject_err::{{closure}} at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:23 4: core::result::Result::map_err at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27 5: soroban_sdk::env::internal::reject_err at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:9 6: ::call at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:1796:13 7: soroban_sdk::env::Env::invoke_contract at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:379:18 8: auth::tests::TestContractClient::exec at ./src/tests.rs:17:1 9: auth::tests::unit_test at ./src/tests.rs:61:5 10: auth::tests::unit_test::{{closure}} at ./src/tests.rs:35:15 11: core::ops::function::FnOnce::call_once at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5 12: core::ops::function::FnOnce::call_once at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5 ``` #### After ``` HostError: Error(Auth, InvalidAction) Event log (newest first): 0: [Diagnostic Event] topics:[error, Error(Auth, InvalidAction)], data:"escalating error to panic" 1: [Diagnostic Event] topics:[error, Error(Auth, InvalidAction)], data:["contract call failed", exec, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4]] 2: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:"caught error from function" 3: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:"escalating error to panic" 4: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, topics:[error, Error(Auth, InvalidAction)], data:["Unauthorized function call for address", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4] 5: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000003), exec], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4 6: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000005), __constructor], data:Void 7: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000004), __constructor], data:Void 8: [Diagnostic Event] topics:[log], data:["holder_2", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM] 9: [Diagnostic Event] topics:[log], data:["holder_1", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAITA4] 10: [Diagnostic Event] topics:[log], data:["test_id", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M] 11: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000003), __constructor], data:Void 12: [Diagnostic Event] topics:[log], data:["auth_id", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4] 13: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4, topics:[fn_return, init], data:Void 14: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000002), init], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 2] 15: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000002), __constructor], data:Void 16: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), __constructor], data:Void stack backtrace: 0: rust_begin_unwind at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5 1: core::panicking::panic_fmt at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14 2: ::escalate_error_to_panic at /Users/leighmcculloch/Code/rs-soroban-env/soroban-env-host/src/host.rs:839:9 3: soroban_sdk::env::internal::reject_err::{{closure}} at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:23 4: core::result::Result::map_err at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27 5: soroban_sdk::env::internal::reject_err at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:52:9 6: ::call at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:1796:13 7: soroban_sdk::env::Env::invoke_contract at /Users/leighmcculloch/.cargo/git/checkouts/rs-soroban-sdk-0ab58a716c671239/a101940/soroban-sdk/src/env.rs:379:18 8: auth::tests::TestContractClient::exec at ./src/tests.rs:17:1 9: auth::tests::unit_test at ./src/tests.rs:61:5 10: auth::tests::unit_test::{{closure}} at ./src/tests.rs:35:15 11: core::ops::function::FnOnce::call_once at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5 12: core::ops::function::FnOnce::call_once at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5 ``` ### Note I'm not attached to this change if we need back traces for something, but if we need to keep them, I'm interested in how we can silence them for errors in contract tests. ### Bonuses As a bonus, this removes 7 deps from the dep graph for contract developers! 🎉 --- soroban-env-host/Cargo.toml | 3 ++- soroban-env-host/src/host/error.rs | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/soroban-env-host/Cargo.toml b/soroban-env-host/Cargo.toml index 66c3a6167..c6275bcf1 100644 --- a/soroban-env-host/Cargo.toml +++ b/soroban-env-host/Cargo.toml @@ -105,7 +105,8 @@ default-features = false features = ["arbitrary"] [features] -testutils = ["soroban-env-common/testutils", "recording_mode", "dep:backtrace"] +testutils = ["soroban-env-common/testutils", "recording_mode"] +backtrace = ["dep:backtrace"] next = ["soroban-env-common/next", "stellar-xdr/next"] tracy = ["dep:tracy-client", "soroban-env-common/tracy"] recording_mode = [] diff --git a/soroban-env-host/src/host/error.rs b/soroban-env-host/src/host/error.rs index d2bfcfca4..6110b1b35 100644 --- a/soroban-env-host/src/host/error.rs +++ b/soroban-env-host/src/host/error.rs @@ -5,7 +5,7 @@ use crate::{ ConversionError, EnvBase, Error, Host, TryFromVal, U32Val, Val, }; -#[cfg(any(test, feature = "testutils"))] +#[cfg(any(test, feature = "backtrace"))] use backtrace::{Backtrace, BacktraceFrame}; use core::fmt::Debug; use std::{ @@ -18,7 +18,7 @@ use super::metered_clone::MeteredClone; #[derive(Clone)] pub(crate) struct DebugInfo { events: Events, - #[cfg(any(test, feature = "testutils"))] + #[cfg(any(test, feature = "backtrace"))] backtrace: Backtrace, } @@ -67,12 +67,12 @@ impl DebugInfo { Ok(()) } - #[cfg(not(any(test, feature = "testutils")))] + #[cfg(not(any(test, feature = "backtrace")))] fn write_backtrace(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { Ok(()) } - #[cfg(any(test, feature = "testutils"))] + #[cfg(any(test, feature = "backtrace"))] fn write_backtrace(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // We do a little trimming here, skipping the first two frames (which // are always into, from, and one or more Host::err_foo calls) and all @@ -296,8 +296,11 @@ impl Host { self.with_debug_mode(|| { if let Ok(events_ref) = self.0.events.try_borrow() { let events = events_ref.externalize(self)?; - let backtrace = Backtrace::new_unresolved(); - res = Some(Box::new(DebugInfo { backtrace, events })); + res = Some(Box::new(DebugInfo { + #[cfg(any(test, feature = "backtrace"))] + backtrace: Backtrace::new_unresolved(), + events, + })); } Ok(()) }); From 02656e6e23f45f8140e5454510f137ab73dba204 Mon Sep 17 00:00:00 2001 From: Dmytro Kozhevin Date: Wed, 18 Sep 2024 13:17:34 -0400 Subject: [PATCH 2/3] Add e2e tests to cover unsupported Wasm upload failure. (#1461) ### What Add e2e tests to cover unsupported Wasm upload failure. While we do cover this at a lower level, it's nice to have an e2e test that makes sure that VM configuration is correct. We also do have e2e tests for completely malformed Wasm failures, this scenario is different because Wasm is not malformed. ### Why Improving test coverage ### Known limitations N/A --- soroban-env-host/src/test/e2e_tests.rs | 49 ++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/soroban-env-host/src/test/e2e_tests.rs b/soroban-env-host/src/test/e2e_tests.rs index bc37aea52..8a136ea3e 100644 --- a/soroban-env-host/src/test/e2e_tests.rs +++ b/soroban-env-host/src/test/e2e_tests.rs @@ -610,6 +610,32 @@ fn test_wasm_upload_success() { assert!(res.budget.get_mem_bytes_consumed().unwrap() > 0); } +#[test] +fn test_wasm_upload_failure_due_to_unsupported_wasm_features() { + let ledger_key = get_wasm_key(ADD_F32); + let ledger_info = default_ledger_info(); + + let res = invoke_host_function_helper( + false, + &upload_wasm_host_fn(ADD_F32), + &resources(10_000_000, vec![], vec![ledger_key.clone()]), + &get_account_id([123; 32]), + vec![], + &ledger_info, + vec![], + &prng_seed(), + ) + .unwrap(); + assert!(res.budget.get_cpu_insns_consumed().unwrap() > 0); + assert!(res.budget.get_mem_bytes_consumed().unwrap() > 0); + + assert!(res.invoke_result.is_err()); + assert!(HostError::result_matches_err( + res.invoke_result, + (ScErrorType::WasmVm, ScErrorCode::InvalidAction) + )); +} + #[test] fn test_wasm_upload_success_in_recording_mode() { let ledger_key = get_wasm_key(ADD_I32); @@ -702,6 +728,29 @@ fn test_wasm_upload_failure_in_recording_mode() { ); } +#[test] +fn test_unsupported_wasm_upload_failure_in_recording_mode() { + let ledger_info = default_ledger_info(); + + let res = invoke_host_function_recording_helper( + true, + &upload_wasm_host_fn(ADD_F32), + &get_account_id([123; 32]), + None, + &ledger_info, + vec![], + &prng_seed(), + None, + ) + .unwrap(); + assert!(res.diagnostic_events.len() >= 1); + assert!(res.contract_events.is_empty()); + assert!(HostError::result_matches_err( + res.invoke_result, + (ScErrorType::WasmVm, ScErrorCode::InvalidAction) + )); +} + #[test] fn test_wasm_upload_success_using_simulation() { let res = invoke_host_function_using_simulation_with_signers( From cf8023a3e05f98f7bc5627d1952b4b33e6746495 Mon Sep 17 00:00:00 2001 From: Siddharth Suresh Date: Wed, 18 Sep 2024 13:11:12 -0700 Subject: [PATCH 3/3] Format contract id in fn_call event topic (#1465) ### What Resolves https://github.com/stellar/rs-soroban-env/issues/1463 Before ``` Event log (newest first): 0: [Diagnostic Event] contract:CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, topics:[error, Error(Contract, https://github.com/stellar/rs-soroban-env/pull/8)], data:["negative amount is not allowed", -1] 1: [Diagnostic Event] topics:[fn_call, Bytes(2e378f80e81a004a1aa7f910dbf45983b9cbb234805c3dbe76a3a4254625f5a9), mint], data:[GD4YHMIZ7IGW7E4XJ4TXIJPLJU255JXPM2PKTV6H4PA4N5RTM6T2R73D, -1] 2: [Diagnostic Event] contract:CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, topics:[fn_return, init_asset], data:Void 3: [Diagnostic Event] topics:[fn_call, Bytes(2e378f80e81a004a1aa7f910dbf45983b9cbb234805c3dbe76a3a4254625f5a9), init_asset], data:Bytes(00000001616161610000000000fc065517dbbca3e37ec0e97dbfcd80e6bcdfdac732be1e4152b259f1f7ea88) ``` After ``` Event log (newest first): 0: [Diagnostic Event] contract:CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, topics:[error, Error(Contract, https://github.com/stellar/rs-soroban-env/pull/8)], data:["negative amount is not allowed", -1] 1: [Diagnostic Event] topics:[fn_call, CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, mint], data:[GD4YHMIZ7IGW7E4XJ4TXIJPLJU255JXPM2PKTV6H4PA4N5RTM6T2R73D, -1] 2: [Diagnostic Event] contract:CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, topics:[fn_return, init_asset], data:Void 3: [Diagnostic Event] topics:[fn_call, CAXDPD4A5ANAASQ2U74RBW7ULGB3TS5SGSAFYPN6O2R2IJKGEX22SWUS, init_asset], data:Bytes(00000001616161610000000000fc065517dbbca3e37ec0e97dbfcd80e6bcdfdac732be1e4152b259f1f7ea88) ``` --- soroban-env-host/src/events/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/soroban-env-host/src/events/mod.rs b/soroban-env-host/src/events/mod.rs index fb70e1ac9..b1c880b98 100644 --- a/soroban-env-host/src/events/mod.rs +++ b/soroban-env-host/src/events/mod.rs @@ -123,11 +123,37 @@ impl core::fmt::Display for HostEvent { match &self.event.body { ContractEventBody::V0(ceb) => { write!(f, "topics:[")?; + + let mut is_fn_call = false; for (i, topic) in ceb.topics.iter().enumerate() { if i != 0 { write!(f, ", ")?; } + + // The second topic of the fn_call event is the contract id as ScBytes, + // but we want to display it as a C key instead, so this block + // tries to deduce if the event is the fn_call event. + if i == 1 && is_fn_call { + if let ScVal::Bytes(bytes) = topic { + let try_convert_to_hash = + TryInto::<[u8; 32]>::try_into(bytes.0.clone()); + if let Ok(contract_id) = try_convert_to_hash { + let strkey = stellar_strkey::Contract(contract_id); + write!(f, "{}", strkey)?; + continue; + } + } + } + display_scval(topic, f)?; + + if i == 0 { + if let ScVal::Symbol(first_topic_str) = topic { + if first_topic_str.0.as_slice() == "fn_call".as_bytes() { + is_fn_call = true; + } + } + } } write!(f, "], data:")?; display_scval(&ceb.data, f)