cosmwasm_std/errors/
system_error.rs

1use alloc::string::String;
2use serde::{Deserialize, Serialize};
3
4use crate::Binary;
5
6/// SystemError is used for errors inside the VM and is API friendly (i.e. serializable).
7///
8/// This is used on return values for Querier as a nested result: Result<StdResult<T>, SystemError>
9/// The first wrap (SystemError) will trigger if the contract address doesn't exist,
10/// the QueryRequest is malformed, etc. The second wrap will be an error message from
11/// the contract itself.
12///
13/// Such errors are only created by the VM. The error type is defined in the standard library, to ensure
14/// the contract understands the error format without creating a dependency on cosmwasm-vm.
15#[derive(
16    Serialize, Deserialize, Clone, Debug, PartialEq, Eq, schemars::JsonSchema, thiserror::Error,
17)]
18#[serde(rename_all = "snake_case")]
19#[non_exhaustive]
20pub enum SystemError {
21    InvalidRequest {
22        error: String,
23        request: Binary,
24    },
25    InvalidResponse {
26        error: String,
27        response: Binary,
28    },
29    NoSuchContract {
30        /// The address that was attempted to query
31        addr: String,
32    },
33    /// A Wasm code was not found.
34    NoSuchCode {
35        /// The code ID that is missing
36        code_id: u64,
37    },
38    Unknown {},
39    UnsupportedRequest {
40        kind: String,
41    },
42}
43
44impl core::fmt::Display for SystemError {
45    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        match self {
47            SystemError::InvalidRequest { error, request } => write!(
48                f,
49                "Cannot parse request: {} in: {}",
50                error,
51                String::from_utf8_lossy(request)
52            ),
53            SystemError::InvalidResponse { error, response } => write!(
54                f,
55                "Cannot parse response: {} in: {}",
56                error,
57                String::from_utf8_lossy(response)
58            ),
59            SystemError::NoSuchContract { addr } => write!(f, "No such contract: {addr}"),
60            SystemError::NoSuchCode { code_id } => write!(f, "No such code: {code_id}"),
61            SystemError::Unknown {} => write!(f, "Unknown system error"),
62            SystemError::UnsupportedRequest { kind } => {
63                write!(f, "Unsupported query type: {kind}")
64            }
65        }
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn system_error_no_such_contract_serialization() {
75        let err = SystemError::NoSuchContract {
76            addr: "gibtsnicht".to_string(),
77        };
78
79        // ser
80        let json = serde_json::to_vec(&err).unwrap();
81        assert_eq!(
82            String::from_utf8_lossy(&json),
83            r#"{"no_such_contract":{"addr":"gibtsnicht"}}"#,
84        );
85
86        // de
87        let err: SystemError =
88            serde_json::from_slice(br#"{"no_such_contract":{"addr":"nada"}}"#).unwrap();
89        assert_eq!(
90            err,
91            SystemError::NoSuchContract {
92                addr: "nada".to_string()
93            }
94        );
95    }
96
97    #[test]
98    fn system_error_no_such_code_serialization() {
99        let err = SystemError::NoSuchCode { code_id: 13 };
100
101        // ser
102        let json = serde_json::to_vec(&err).unwrap();
103        assert_eq!(
104            String::from_utf8_lossy(&json),
105            r#"{"no_such_code":{"code_id":13}}"#,
106        );
107
108        // de
109        let err: SystemError =
110            serde_json::from_slice(br#"{"no_such_code":{"code_id":987}}"#).unwrap();
111        assert_eq!(err, SystemError::NoSuchCode { code_id: 987 },);
112    }
113}