cosmwasm_std/errors/
system_error.rs

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