Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the readability of stack traces #1458

Open
leighmcculloch opened this issue Sep 12, 2024 · 8 comments
Open

Improve the readability of stack traces #1458

leighmcculloch opened this issue Sep 12, 2024 · 8 comments

Comments

@leighmcculloch
Copy link
Member

I think we should improve the readability of the diagnostic event and stack trace outputs that the environment generates on the console and in tests when there are failures.

This is not about improving the contents / data within the diagnostic events, and only the presentation of the existing data, so it is easier to glance and digest.

An example of the existing output as of v21.2.1:

thread 'test::test_sample_policy_call_self' panicked at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:768:9:
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", add, [[Policy, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4], [Temporary], [Admin]]]]
   2: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[error, Error(Auth, InvalidAction)], data:"caught error from function"
   3: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[error, Error(Auth, InvalidAction)], data:"escalating error to panic"
   4: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[error, Error(Auth, InvalidAction)], data:["Unauthorized function call for address", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM]
   5: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], data:[Policy, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4], [Temporary], [Admin]]
   6: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[fn_return, add], data:Void
   7: [Contract Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[sw_v1, add, [Ed25519, [Bytes(a1738d72617d88f775693c9b9033d8bbb99d127ea9ac0f04940dd090350c5b4e)]]], data:[Ed25519, [Admin]]
   8: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], data:[Ed25519, [Bytes(a1738d72617d88f775693c9b9033d8bbb99d127ea9ac0f04940dd090350c5b4e)], [Persistent], [Admin]]
   9: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[fn_return, add], data:Void
   10: [Contract Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, topics:[sw_v1, add, [Secp256r1, [Bytes(f3f8d84ae2da5566c4a70e977c2a49888a66bb8c)]]], data:[Secp256r1, [Bytes(04a38ef5f2713768bd3480eeceaec2b10464a1f3b1ff0a3539c2cd2dd00a83a75d2c7b7e5fdbcfe6af5a602979c57fb44aeca0003cb9d3ae85d7c8d0e633d25ed6)], [Admin]]
   11: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], data:[Secp256r1, [Bytes(f3f8d84ae2da5566c4a70e977c2a49888a66bb8c)], [Bytes(04a38ef5f2713768bd3480eeceaec2b10464a1f3b1ff0a3539c2cd2dd00a83a75d2c7b7e5fdbcfe6af5a602979c57fb44aeca0003cb9d3ae85d7c8d0e633d25ed6)], [Persistent], [Admin]]

Backtrace (newest first):
   0: backtrace::backtrace::libunwind::trace
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.69/src/backtrace/libunwind.rs:93:5
      backtrace::backtrace::trace_unsynchronized
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.69/src/backtrace/mod.rs:66:5
   1: backtrace::backtrace::trace
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.69/src/backtrace/mod.rs:53:14
   2: backtrace::capture::Backtrace::create
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.69/src/capture.rs:176:9
   3: backtrace::capture::Backtrace::new_unresolved
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.69/src/capture.rs:170:9
   4: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info::{{closure}}
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:293:37
   5: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
   6: soroban_env_host::host::Host::with_debug_mode
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
   7: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:290:13
   8: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error::{{closure}}
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:274:23
   9: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
  10: soroban_env_host::host::Host::with_debug_mode
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
  11: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:261:9
  12: <soroban_env_host::host::Host as soroban_env_common::env::EnvBase>::escalate_error_to_panic
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:767:26
  13: soroban_sdk::env::internal::reject_err::{{closure}}
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:52:23
  14: core::result::Result<T,E>::map_err
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27
  15: soroban_sdk::env::internal::reject_err
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:52:9
  16: <soroban_sdk::env::Env as soroban_env_common::env::Env>::call
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:1667:13
  17: soroban_sdk::env::Env::invoke_contract
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:379:18
  18: webauthn_wallet::ContractClient::add
             at src/lib.rs:28:1
  19: webauthn_wallet::test::test_sample_policy_call_self
             at src/test.rs:128:5
  20: webauthn_wallet::test::test_sample_policy_call_self::{{closure}}
             at src/test.rs:30:34
  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: <soroban_env_host::host::Host as soroban_env_common::env::EnvBase>::escalate_error_to_panic
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:768:9
   3: soroban_sdk::env::internal::reject_err::{{closure}}
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:52:23
   4: core::result::Result<T,E>::map_err
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27
   5: soroban_sdk::env::internal::reject_err
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:52:9
   6: <soroban_sdk::env::Env as soroban_env_common::env::Env>::call
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:1667:13
   7: soroban_sdk::env::Env::invoke_contract
             at /Users/tylervanderhoeven/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.0/src/env.rs:379:18
   8: webauthn_wallet::ContractClient::add
             at ./src/lib.rs:28:1
   9: webauthn_wallet::test::test_sample_policy_call_self
             at ./src/test.rs:128:5
  10: webauthn_wallet::test::test_sample_policy_call_self::{{closure}}
             at ./src/test.rs:30:34
  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
@leighmcculloch
Copy link
Member Author

leighmcculloch commented Sep 12, 2024

Some examples of panic outputs in different environments for inspiration are below. They use very simple inputs, so their utility may be limited, but maybe we can learn something from them. I also understand that the diagnostic events are not stack traces, and they don't point to code, but developers sort of treat them as similar, as a way to understand where the program was when something went wrong.

Rust
fn main() {
	f1(1)
}

fn f1(i: u32) {
	f2()
}

fn f2() {
	f3()
}

fn f3() {
	panic!("oh no")
}
thread 'main' panicked at src/main.rs:14:5:
oh no
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: ruttest::f3
             at ./src/main.rs:14:2
   3: ruttest::f2
             at ./src/main.rs:10:2
   4: ruttest::f1
             at ./src/main.rs:6:2
   5: ruttest::main
             at ./src/main.rs:2:2
   6: core::ops::function::FnOnce::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5
Go
package main

func main() {
	f1(1)
}

func f1(i int) {
	f2()
}

func f2() {
	f3()
}

func f3() {
	panic("oh no")
}
panic: oh no

goroutine 1 [running]:
main.f3(...)
        /Users/leighmcculloch/Code/gotest/main.go:16
main.f2(...)
        /Users/leighmcculloch/Code/gotest/main.go:12
main.f1(...)
        /Users/leighmcculloch/Code/gotest/main.go:8
main.main()
        /Users/leighmcculloch/Code/gotest/main.go:4 +0x38
exit status 2
Node
function f1(i) {
  f2();
}

function f2() {
  f3();
}

function f3() {
  throw "oh no";
}

f1(1);
/Users/leighmcculloch/Code/nodtest/main.js:10
  throw "oh no";
  ^
oh no
Thrown at:
    at f3 (/Users/leighmcculloch/Code/nodtest/main.js:10:3)
    at f2 (/Users/leighmcculloch/Code/nodtest/main.js:6:3)
    at f1 (/Users/leighmcculloch/Code/nodtest/main.js:2:3)
    at /Users/leighmcculloch/Code/nodtest/main.js:13:1
    at Module._compile (node:internal/modules/cjs/loader:1378:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1437:10)
    at Module.load (node:internal/modules/cjs/loader:1212:32)
    at Module._load (node:internal/modules/cjs/loader:1028:12)
    at executeUserEntryPoint (node:internal/modules/run_main:142:12)
    at node:internal/main/run_main_module:28:49
Bun
function f1(i) {
  f2();
}

function f2() {
  f3();
}

function f3() {
  throw "oh no";
}

f1(1);
error: oh no
Deno
function f1(i: u32) {
  f2();
}

function f2() {
  f3();
}

function f3() {
  throw "oh no";
}

f1(1);
error: Uncaught (in promise) "oh no"
Python
def f1(i):
  f2()

def f2():
  f3()

def f3():
  raise Exception("oh no")

f1(1)
Traceback (most recent call last):
  File "/Users/leighmcculloch/Code/pytest/main.py", line 10, in <module>
    f1(1)
  File "/Users/leighmcculloch/Code/pytest/main.py", line 2, in f1
    f2()
  File "/Users/leighmcculloch/Code/pytest/main.py", line 5, in f2
    f3()
  File "/Users/leighmcculloch/Code/pytest/main.py", line 8, in f3
    raise Exception("oh no")
Exception: oh no
Ruby
def f1(i)
  f2()
end

def f2()
  f3()
end

def f3()
  raise "oh no"
end

f1(1)
main.rb:10:in `f3': oh no (RuntimeError)
        from main.rb:6:in `f2'
        from main.rb:2:in `f1'
        from main.rb:13:in `<main>'
Java
public class Main {
    public static void main(String[] args) {
        f1(1);
    }

    public static void f1(int i) {
        f2();
    }

    public static void f2() {
        f3();
    }

    public static void f3() {
        throw new RuntimeException("oh no");
    }
}
Exception in thread "main" java.lang.RuntimeException: oh no
  at Main.f3(Main.java:15)
  at Main.f2(Main.java:11)
  at Main.f1(Main.java:7)
  at Main.main(Main.java:3)
.NET
using System;
          
public class Program
{
  public static void Main()
  {
    f1(1);
  }
  
  public static void f1(int i) {
    f2();
  }
  
  public static void f2() {
    f3();
  }
  
  public static void f3() {
    throw new Exception("oh no");
  }
}
Run-time exception (line 19): oh no

Stack Trace:

[System.Exception: oh no]
   at Program.f3() :line 19
   at Program.f2() :line 15
   at Program.f1(Int32 i) :line 11
   at Program.Main() :line 7
Swift
import Foundation

func f1(i: Int) {
    f2();
}

func f2() {
    f3();
}

func f3() {
    fatalError("oh no");
}

f1(i: 1);
main/main.swift:12: Fatal error: oh no
[1]    30171 trace trap  ./main
Zig
pub fn main() !void {
  f1(1);
}

fn f1(_: i32) void {
  f2();
}

fn f2() void {
  f3();
}

fn f3() void {
  @panic("oh no");
}
thread 22449779 panic: oh no
/Users/leighmcculloch/Code/zigtest/main.zig:14:3: 0x102242e4b in f3 (main)
  @panic("oh no");
  ^
/Users/leighmcculloch/Code/zigtest/main.zig:10:5: 0x1022416af in f2 (main)
  f3();
    ^
/Users/leighmcculloch/Code/zigtest/main.zig:6:5: 0x102240797 in f1 (main)
  f2();
    ^
/Users/leighmcculloch/Code/zigtest/main.zig:2:5: 0x102240777 in main (main)
  f1(1);
    ^
/opt/homebrew/Cellar/zig/0.13.0/lib/zig/std/start.zig:524:37: 0x1022409fb in main (main)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x189b2a0df in ??? (???)
???:?:?: 0x9900ffffffffffff in ??? (???)
[1]    33104 abort      zig run main.zig

@kalepail
Copy link

My main interest is mostly just readability. So adding more whitespace and line breaks would go a long way towards legibility.

e.g.

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", add, [[Policy, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4], [Temporary], [Admin]]]]
2: [Failed Diagnostic Event (not emitted)] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[error, Error(Auth, InvalidAction)], data:"caught error from function"
3: [Failed Diagnostic Event (not emitted)] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[error, Error(Auth, InvalidAction)], 
   data:"escalating error to panic"
4: [Failed Diagnostic Event (not emitted)] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[error, Error(Auth, InvalidAction)], 
   data:["Unauthorized function call for address", CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM]
5: [Diagnostic Event] 
   topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], 
   data:[Policy, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4], [Temporary], [Admin]]
6: [Diagnostic Event] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[fn_return, add], 
   data:Void
7: [Contract Event] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[sw_v1, add, [Ed25519, [Bytes(a1738d72617d88f775693c9b9033d8bbb99d127ea9ac0f04940dd090350c5b4e)]]], 
   data:[Ed25519, [Admin]]
8: [Diagnostic Event] 
   topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], 
   data:[Ed25519, [Bytes(a1738d72617d88f775693c9b9033d8bbb99d127ea9ac0f04940dd090350c5b4e)], [Persistent], [Admin]]
9: [Diagnostic Event] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[fn_return, add], 
   data:Void
10: [Contract Event] 
   contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2KM, 
   topics:[sw_v1, add, [Secp256r1, [Bytes(f3f8d84ae2da5566c4a70e977c2a49888a66bb8c)]]], 
   data:[Secp256r1, [Bytes(04a38ef5f2713768bd3480eeceaec2b10464a1f3b1ff0a3539c2cd2dd00a83a75d2c7b7e5fdbcfe6af5a602979c57fb44aeca0003cb9d3ae85d7c8d0e633d25ed6)], [Admin]]
11: [Diagnostic Event] 
   topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000001), add], 
   data:[Secp256r1, [Bytes(f3f8d84ae2da5566c4a70e977c2a49888a66bb8c)], [Bytes(04a38ef5f2713768bd3480eeceaec2b10464a1f3b1ff0a3539c2cd2dd00a83a75d2c7b7e5fdbcfe6af5a602979c57fb44aeca0003cb9d3ae85d7c8d0e633d25ed6)], [Persistent], [Admin]]

You could further break up arrays by comma if you wanted to but that would start to make stack traces very very long.

@kalepail
Copy link

Idk if we have the ability to color anything but highlighting actual error messages would also be really nice.

e.g. from above these are really the meat of the error
"escalating error to panic"
"contract call failed"
"caught error from function"
"escalating error to panic"
"Unauthorized function call for address"

@tupui
Copy link

tupui commented Oct 21, 2024

Great to see this being worked on, thank you! 😃

I have posted that example on twitter in Tomer's thread. Thank you again for your reply.

The task becomes very challenging if you are trying to do cross-contract calls. I understand a bit how that works (I helped polish the doc on that part during the last bounty) and once you get how to call another contract from yours, the next challenge becomes: how to read these errors.

Here is an example on my project. I am calling Soroban Domains to register a domain. If I deliberately change that line and use a non valid TLD (these 3 bytes write xlm)

https://github.com/tupui/soroban-versioning/blob/828bf95846fcdb5fa884ca5c7bb6f3ca73986017/contracts/versioning/src/lib.rs#L209

Then it will result in this panic.

Trace

/Users/tupui/.cargo/bin/cargo test --color=always --profile test --workspace --no-fail-fast --config env.RUSTC_BOOTSTRAP=\"1\" -- --format=json -Z unstable-options --show-output
Testing started at 23:43 ...
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.07s
     Running unittests src/lib.rs (target/debug/deps/versioning-0b6e8f3c06df1343)

HostError: Error(Contract, #4)

Event log (newest first):
   0: [Diagnostic Event] topics:[error, Error(Contract, #4)], data:"escalating error to panic"
   1: [Diagnostic Event] topics:[error, Error(Contract, #4)], data:["contract call failed", register, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "tansu", [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5], "github.com/file.toml", "2ef4f49fdd8fa9dc463f1f06a094c26b88710990", CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V]]
   2: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:"caught error from function"
   3: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:"escalating error to panic"
   4: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:["contract call failed", set_record, [Bytes(74616e7375), Bytes(786c), CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 31536000]]
   5: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[log], data:["VM call trapped with HostError", set_record, Error(Contract, #4)]
   6: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[error, Error(Contract, #4)], data:"escalating error to VM trap from failed host function call: fail_with_error"
   7: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[error, Error(Contract, #4)], data:["failing with contract error", 4]
   8: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), set_record], data:[Bytes(74616e7375), Bytes(786c), CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 31536000]
   9: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[fn_return, record], data:Void
   10: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), record], data:[Record, Bytes(2324dc49faf83ad010cee02118b8244566e3f9065e94a2694a8f57e377f7275c)]
   11: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000006), register], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "tansu", [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5], "github.com/file.toml", "2ef4f49fdd8fa9dc463f1f06a094c26b88710990", CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V]
   12: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, mint], data:Void
   13: [Contract Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[mint, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF"], data:10000000000000000
   14: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), mint], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 10000000000000000]
   15: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_return, init], data:Void
   16: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000006), init], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM
   17: [Diagnostic Event] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[fn_return, init], data:Void
   18: [Diagnostic Event] topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), init], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4, 100, CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, 31536000, [Bytes(786c6d), Bytes(7374656c6c6172), Bytes(77616c6c6574), Bytes(64616f)]]
   19: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, set_admin], data:Void
   20: [Contract Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[set_admin, GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF, "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF"], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M
   21: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), set_admin], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M
   22: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, init_asset], data:Void
   23: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), init_asset], data:Bytes(0000000161616100000000000000000000000000000000000000000000000000000000000000000000000004)

Backtrace (newest first):
   0: backtrace::backtrace::libunwind::trace
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/libunwind.rs:116:5
      backtrace::backtrace::trace_unsynchronized
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:66:5
   1: backtrace::backtrace::trace
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:53:14
   2: backtrace::capture::Backtrace::create
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:292:9
   3: backtrace::capture::Backtrace::new_unresolved
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:287:9
   4: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:293:37
   5: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
   6: soroban_env_host::host::Host::with_debug_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
   7: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:290:13
   8: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:274:23
   9: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
  10: soroban_env_host::host::Host::with_debug_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
  11: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:261:9
  12: <soroban_env_host::host::Host as soroban_env_common::env::EnvBase>::escalate_error_to_panic
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:767:26
  13: soroban_sdk::env::internal::reject_err::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:23
  14: core::result::Result<T,E>::map_err
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27
  15: soroban_sdk::env::internal::reject_err
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:9
  16: <soroban_sdk::env::Env as soroban_env_common::env::Env>::call
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:1667:13
  17: soroban_sdk::env::Env::invoke_contract
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:379:18
  18: versioning::VersioningClient::register
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/lib.rs:56:1
  19: versioning::test::test
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/test.rs:62:14
  20: versioning::test::test::{{closure}}
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/test.rs:12:10
  21: core::ops::function::FnOnce::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5
thread 'test::test' panicked at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:768:9:
HostError: Error(Contract, #4)

Event log (newest first):
   0: [Diagnostic Event] topics:[error, Error(Contract, #4)], data:"escalating error to panic"
   1: [Diagnostic Event] topics:[error, Error(Contract, #4)], data:["contract call failed", register, [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "tansu", [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5], "github.com/file.toml", "2ef4f49fdd8fa9dc463f1f06a094c26b88710990", CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V]]
   2: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:"caught error from function"
   3: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:"escalating error to panic"
   4: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[error, Error(Contract, #4)], data:["contract call failed", set_record, [Bytes(74616e7375), Bytes(786c), CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 31536000]]
   5: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[log], data:["VM call trapped with HostError", set_record, Error(Contract, #4)]
   6: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[error, Error(Contract, #4)], data:"escalating error to VM trap from failed host function call: fail_with_error"
   7: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[error, Error(Contract, #4)], data:["failing with contract error", 4]
   8: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), set_record], data:[Bytes(74616e7375), Bytes(786c), CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 31536000]
   9: [Failed Diagnostic Event (not emitted)] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[fn_return, record], data:Void
   10: [Failed Diagnostic Event (not emitted)] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), record], data:[Record, Bytes(2324dc49faf83ad010cee02118b8244566e3f9065e94a2694a8f57e377f7275c)]
   11: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000006), register], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "tansu", [CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQG5], "github.com/file.toml", "2ef4f49fdd8fa9dc463f1f06a094c26b88710990", CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V]
   12: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, mint], data:Void
   13: [Contract Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[mint, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M, CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF"], data:10000000000000000
   14: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), mint], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOLZM, 10000000000000000]
   15: [Diagnostic Event] contract:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDR4, topics:[fn_return, init], data:Void
   16: [Diagnostic Event] topics:[fn_call, Bytes(0000000000000000000000000000000000000000000000000000000000000006), init], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK3IM
   17: [Diagnostic Event] contract:CBKMUZNFQIAL775XBB2W2GP5CNHBM5YGH6C3XB7AY6SUVO2IBU3VYK2V, topics:[fn_return, init], data:Void
   18: [Diagnostic Event] topics:[fn_call, Bytes(54ca65a58200bfffb708756d19fd134e1677063f85bb87e0c7a54abb480d375c), init], data:[CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCT4, 100, CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, 31536000, [Bytes(786c6d), Bytes(7374656c6c6172), Bytes(77616c6c6574), Bytes(64616f)]]
   19: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, set_admin], data:Void
   20: [Contract Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[set_admin, GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF, "aaa:GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJXFF"], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M
   21: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), set_admin], data:CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHK3M
   22: [Diagnostic Event] contract:CCABDO7UZXYE4W6GVSEGSNNZTKSLFQGKXXQTH6OX7M7GKZ4Z6CUJNGZN, topics:[fn_return, init_asset], data:Void
   23: [Diagnostic Event] topics:[fn_call, Bytes(8011bbf4cdf04e5bc6ac886935b99aa4b2c0cabde133f9d7fb3e656799f0a896), init_asset], data:Bytes(0000000161616100000000000000000000000000000000000000000000000000000000000000000000000004)

Backtrace (newest first):
   0: backtrace::backtrace::libunwind::trace
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/libunwind.rs:116:5
      backtrace::backtrace::trace_unsynchronized
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:66:5
   1: backtrace::backtrace::trace
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/backtrace/mod.rs:53:14
   2: backtrace::capture::Backtrace::create
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:292:9
   3: backtrace::capture::Backtrace::new_unresolved
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/backtrace-0.3.74/src/capture.rs:287:9
   4: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:293:37
   5: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
   6: soroban_env_host::host::Host::with_debug_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
   7: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::maybe_get_debug_info
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:290:13
   8: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:274:23
   9: soroban_env_host::budget::Budget::with_shadow_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/budget.rs:972:21
  10: soroban_env_host::host::Host::with_debug_mode
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:615:24
  11: soroban_env_host::host::error::<impl soroban_env_host::host::Host>::error
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host/error.rs:261:9
  12: <soroban_env_host::host::Host as soroban_env_common::env::EnvBase>::escalate_error_to_panic
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:767:26
  13: soroban_sdk::env::internal::reject_err::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:23
  14: core::result::Result<T,E>::map_err
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27
  15: soroban_sdk::env::internal::reject_err
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:9
  16: <soroban_sdk::env::Env as soroban_env_common::env::Env>::call
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:1667:13
  17: soroban_sdk::env::Env::invoke_contract
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:379:18
  18: versioning::VersioningClient::register
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/lib.rs:56:1
  19: versioning::test::test
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/test.rs:62:14
  20: versioning::test::test::{{closure}}
             at /Users/tupui/Documents/Code/soroban-versioning/contracts/versioning/src/test.rs:12:10
  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: <soroban_env_host::host::Host as soroban_env_common::env::EnvBase>::escalate_error_to_panic
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-env-host-21.2.1/src/host.rs:768:9
   3: soroban_sdk::env::internal::reject_err::{{closure}}
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:23
   4: core::result::Result<T,E>::map_err
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/result.rs:854:27
   5: soroban_sdk::env::internal::reject_err
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:52:9
   6: <soroban_sdk::env::Env as soroban_env_common::env::Env>::call
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:1667:13
   7: soroban_sdk::env::Env::invoke_contract
             at /Users/tupui/.cargo/registry/src/index.crates.io-6f17d22bba15001f/soroban-sdk-21.7.4/src/env.rs:379:18
   8: versioning::VersioningClient::register
             at ./src/lib.rs:56:1
   9: versioning::test::test
             at ./src/test.rs:62:14
  10: versioning::test::test::{{closure}}
             at ./src/test.rs:12:10
  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: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Writing test snapshot file for test "test::test" to "test_snapshots/test/test.1.json".

Writing test snapshot file for test "test::test_utils" to "test_snapshots/test/test_utils.1.json".
error: test failed, to rerun pass `--lib`
error: 1 target failed:
    `--lib`

Process finished with exit code 101

There are a few things here. First the stacktrace is too long 😅 It's showing me too much of what happened with previous calls I made running the test suite. It took me a while, too long I care to admit, to actually understand that and it was not relevant to my issue. Removing all that, we are left with 10 items, still a bit too long and there is quite some repetition due to this escalation in the stack. What you might eventually start to notice is the repetition of Error(Contract, #4)]. It took me a while to also get what this was: the error code thrown by Soroban Domains contract itself. But what is this 4. Here you have to find the source code to finally get to it (can also not be that obvious to find):

https://github.com/Creit-Tech/sorobandomains-sc/blob/main/contracts/registry/src/errors.rs

And here we have it in the enum: UnsupportedTLD = 4. (Getting the correct parameters is another story in itself 😅 same with making tests.)


I am not sure how all that is possible, but if there was a way to resurface better the meaning of error codes, that would be really helpful. Then, adding colors as @kalepail suggest could be super helpful to separate sections. This could also be accomplished by splitting a bit more the output of the trace. I guess in some cases you want this super verbose output and my case is "too simple". But that's the thing to me simple cases like these should be simple to debug and for now it's hard.

Hope that helps 😃

@leighmcculloch
Copy link
Member Author

leighmcculloch commented Oct 22, 2024

@tupui Thank you for sharing more details and an example, this is helpful as we think about how to restructure this data.


Here you have to find the source code to finally get to it (can also not be that obvious to find):

https://github.com/Creit-Tech/sorobandomains-sc/blob/main/contracts/registry/src/errors.rs

And here we have it in the enum: UnsupportedTLD = 4.

Fyi if you have the .wasm for the contract, or you know it's address on chain, you can lookup the error using the specification without the source.

$ stellar contract info interface --network testnet --id CADDH3WW3EHDEUY4HIQUAZHRPCFQFL4MZIEZBFUIIHJAXZNLQWVC6DV4
...
pub enum ContractErrors {
    UnexpectedError = 0,
    AlreadyStarted = 1,
    RecordAlreadyExist = 2,
    InvalidDuration = 3,
    UnsupportedTLD = 4,
    RecordDoesntExist = 5,
    InvalidDomain = 6,
    ExpiredDomain = 7,
    InvalidParent = 8,
    OutdatedSub = 9,
    InvalidTransfer = 10,
    InvalidOfferAmount = 11,
    OutdatedOffer = 12,
    OfferDoesntExist = 13,
}

@Ifropc Maybe we should add another sub-command to contract info, such as contract info errors, that just outputs a json mapping of errors to error codes 🤔

@tupui
Copy link

tupui commented Oct 22, 2024

Thanks, I did not know that command 👍 That will help in such cases. Might be more tricky if the underlying contract does not properly validate inputs and would break (I did not check, so just talking hypothetically here.)

@tupui
Copy link

tupui commented Nov 24, 2024

I am not sure if this is the right place, but I found another interesting case with some obscure error message.

If you are using storage, at compile time it does not tell you if you are using the correct type to store and update values.

e.g. with this structure

#[contracttype]
pub struct Proposal {
    ...
}

#[contracttype]
pub struct Dao {
    pub proposals: Vec<Proposal>,
}

#[contracttype]
pub enum ProjectKey {
    ...
    DaoTotalProposals(Bytes),
}

I was wrongly updating an entry of ProjectKey::Dao with Proposal although I had first set the value to be Dao

env.storage()
    .persistent()
    .set(&ProjectKey::Dao(project_key, page), &proposal)

And this gives this error

differing host map and output slice lengths when unpacking map to slice

(Additionally it was also not pointing directly to the problematic line but I could find that using RustRover's debugger.)

This bugged me for a while. Here I got some luck with Stella 😅

This specific error occurs when trying to retrieve data from storage where there's a mismatch between the data structure you're trying to deserialize into and the actual data stored.
...
    // Make sure this matches exactly what was stored
    // Including all fields and their types
Stella's full response

Understanding the Storage Get Error

This specific error occurs when trying to retrieve data from storage where there's a mismatch between the data structure you're trying to deserialize into and the actual data stored.

Common Causes

  1. Data Type Mismatch
// If you stored data as one type
#[derive(Clone)]
#[contracttype]
pub struct OldDao {
    field1: String,
    field2: i32,
}

// But trying to retrieve as another type
#[derive(Clone)]
#[contracttype]
pub struct NewDao {
    field1: String,
    field2: i32,
    field3: Vec<String>, // Added field
}

How to Fix

  1. Verify Your Data Structure
#[derive(Clone)]
#[contracttype]
pub struct Dao {
    // Make sure this matches exactly what was stored
    // Including all fields and their types
}

// When retrieving
let dao: Dao = env.storage().persistent()
    .get(&DataKey::Dao(project_key, page))
    .unwrap_or_else(|| panic!("Not found"));
  1. Check if Data Exists
// Safe retrieval with error handling
if let Some(dao) = env.storage().persistent().get(&DataKey::Dao(project_key, page)) {
    // Data exists and matches the type
} else {
    // Handle case where data doesn't exist
}

Best Practices

  1. Always keep track of your contract's data structure versions
  2. When updating contracts, ensure compatibility with existing stored data
  3. Consider implementing migration strategies for data structure changes

If the error persists, try:

  • Checking the exact type definition used when the data was stored
  • Verifying the storage key structure matches what was used for storing
  • Using debug prints to confirm the data exists in storage

Sources:
stellar/rs-soroban-sdk#831
What does the error symbol not found in slice of strs indicate?
stellar/rs-soroban-sdk#787
⁠Contract (Soroswap) Integration

@leighmcculloch
Copy link
Member Author

leighmcculloch commented Nov 25, 2024

I can see how that error message didn't point at the issue at all. This is, in general, the issue with errors within host functions, they have no context where they're being used and for what. So in this case that host function was being used for custom type struct unpacking. The context about that is in the sdk, but the error is being raised and the contract is being terminated before returning back to the contract where the context is.

That's cool to see Stella bot could recognise the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants