revive_solc_json_interface/standard_json/output/error/
mod.rs1pub mod source_location;
4
5use std::str::FromStr;
6
7use serde::Deserialize;
8use serde::Serialize;
9
10use self::source_location::SourceLocation;
11
12#[derive(Debug, Serialize, Deserialize, Clone)]
14#[serde(rename_all = "camelCase")]
15pub struct Error {
16 pub component: String,
18 pub error_code: Option<String>,
20 pub formatted_message: String,
22 pub message: String,
24 pub severity: String,
26 pub source_location: Option<SourceLocation>,
28 pub r#type: String,
30}
31
32impl Error {
33 pub fn message_ecrecover(src: Option<&str>) -> Self {
35 let message = r#"
36Warning: It looks like you are using 'ecrecover' to validate a signature of a user account.
37Polkadot comes with native account abstraction support, therefore it is highly recommended NOT
38to rely on the fact that the account has an ECDSA private key attached to it since accounts might
39implement other signature schemes.
40"#
41 .to_owned();
42
43 Self {
44 component: "general".to_owned(),
45 error_code: None,
46 formatted_message: message.clone(),
47 message,
48 severity: "warning".to_owned(),
49 source_location: src.map(SourceLocation::from_str).and_then(Result::ok),
50 r#type: "Warning".to_owned(),
51 }
52 }
53
54 pub fn message_send_and_transfer(src: Option<&str>) -> Self {
56 let message = r#"
57Warning: It looks like you are using '<address payable>.send/transfer(<X>)'.
58Using '<address payable>.send/transfer(<X>)' is deprecated and strongly discouraged!
59The resolc compiler uses a heuristic to detect '<address payable>.send/transfer(<X>)' calls,
60which disables call re-entrancy and supplies all remaining gas instead of the 2300 gas stipend.
61However, detection is not guaranteed. You are advised to carefully test this, employ
62re-entrancy guards or use the withdrawal pattern instead!
63Learn more on https://docs.soliditylang.org/en/latest/security-considerations.html#reentrancy
64and https://docs.soliditylang.org/en/latest/common-patterns.html#withdrawal-from-contracts
65"#
66 .to_owned();
67
68 Self {
69 component: "general".to_owned(),
70 error_code: None,
71 formatted_message: message.clone(),
72 message,
73 severity: "warning".to_owned(),
74 source_location: src.map(SourceLocation::from_str).and_then(Result::ok),
75 r#type: "Warning".to_owned(),
76 }
77 }
78
79 pub fn message_extcodesize(src: Option<&str>) -> Self {
81 let message = r#"
82Warning: Your code or one of its dependencies uses the 'extcodesize' instruction, which is
83usually needed in the following cases:
84 1. To detect whether an address belongs to a smart contract.
85 2. To detect whether the deploy code execution has finished.
86Polkadot comes with native account abstraction support (so smart contracts are just accounts
87coverned by code), and you should avoid differentiating between contracts and non-contract
88addresses.
89"#
90 .to_owned();
91
92 Self {
93 component: "general".to_owned(),
94 error_code: None,
95 formatted_message: message.clone(),
96 message,
97 severity: "warning".to_owned(),
98 source_location: src.map(SourceLocation::from_str).and_then(Result::ok),
99 r#type: "Warning".to_owned(),
100 }
101 }
102
103 pub fn message_tx_origin(src: Option<&str>) -> Self {
105 let message = r#"
106Warning: You are checking for 'tx.origin' in your code, which might lead to unexpected behavior.
107Polkadot comes with native account abstraction support, and therefore the initiator of a
108transaction might be different from the contract calling your code. It is highly recommended NOT
109to rely on tx.origin, but use msg.sender instead.
110"#
111 .to_owned();
112
113 Self {
114 component: "general".to_owned(),
115 error_code: None,
116 formatted_message: message.clone(),
117 message,
118 severity: "warning".to_owned(),
119 source_location: src.map(SourceLocation::from_str).and_then(Result::ok),
120 r#type: "Warning".to_owned(),
121 }
122 }
123
124 pub fn push_contract_path(&mut self, path: &str) {
126 self.formatted_message
127 .push_str(format!("\n--> {path}\n").as_str());
128 }
129}
130
131impl std::fmt::Display for Error {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 write!(f, "{}", self.formatted_message)
134 }
135}