1#[derive(Clone, Debug, Eq, PartialEq)]
11pub enum ProgramError {
12 Custom(u32),
14 InvalidArgument,
15 InvalidInstructionData,
16 InvalidAccountData,
17 AccountDataTooSmall,
18 InsufficientFunds,
19 IncorrectProgramId,
20 MissingRequiredSignature,
21 AccountAlreadyInitialized,
22 UninitializedAccount,
23 NotEnoughAccountKeys,
24 AccountBorrowFailed,
25 MaxSeedLengthExceeded,
26 InvalidSeeds,
27 BorshIoError,
28 AccountNotRentExempt,
29 UnsupportedSysvar,
30 IllegalOwner,
31 MaxAccountsDataAllocationsExceeded,
32 InvalidRealloc,
33 MaxInstructionTraceLengthExceeded,
34 BuiltinProgramsMustConsumeComputeUnits,
35 InvalidAccountOwner,
36 ArithmeticOverflow,
37 Immutable,
38 IncorrectAuthority,
39}
40
41const BUILTIN_BIT_SHIFT: usize = 32;
45const CUSTOM_ZERO: u64 = 1_u64 << BUILTIN_BIT_SHIFT;
46
47#[inline(always)]
51const fn to_builtin(index: u64) -> u64 {
52 (index + 2) << BUILTIN_BIT_SHIFT
53}
54
55const BUILTIN_LOW_MASK: u64 = (1_u64 << BUILTIN_BIT_SHIFT) - 1;
56
57impl From<ProgramError> for u64 {
58 fn from(err: ProgramError) -> u64 {
59 match err {
60 ProgramError::Custom(0) => CUSTOM_ZERO,
61 ProgramError::Custom(code) => code as u64,
62 ProgramError::InvalidArgument => to_builtin(0),
63 ProgramError::InvalidInstructionData => to_builtin(1),
64 ProgramError::InvalidAccountData => to_builtin(2),
65 ProgramError::AccountDataTooSmall => to_builtin(3),
66 ProgramError::InsufficientFunds => to_builtin(4),
67 ProgramError::IncorrectProgramId => to_builtin(5),
68 ProgramError::MissingRequiredSignature => to_builtin(6),
69 ProgramError::AccountAlreadyInitialized => to_builtin(7),
70 ProgramError::UninitializedAccount => to_builtin(8),
71 ProgramError::NotEnoughAccountKeys => to_builtin(9),
72 ProgramError::AccountBorrowFailed => to_builtin(10),
73 ProgramError::MaxSeedLengthExceeded => to_builtin(11),
74 ProgramError::InvalidSeeds => to_builtin(12),
75 ProgramError::BorshIoError => to_builtin(13),
76 ProgramError::AccountNotRentExempt => to_builtin(14),
77 ProgramError::UnsupportedSysvar => to_builtin(15),
78 ProgramError::IllegalOwner => to_builtin(16),
79 ProgramError::MaxAccountsDataAllocationsExceeded => to_builtin(17),
80 ProgramError::InvalidRealloc => to_builtin(18),
81 ProgramError::MaxInstructionTraceLengthExceeded => to_builtin(19),
82 ProgramError::BuiltinProgramsMustConsumeComputeUnits => to_builtin(20),
83 ProgramError::InvalidAccountOwner => to_builtin(21),
84 ProgramError::ArithmeticOverflow => to_builtin(22),
85 ProgramError::Immutable => to_builtin(23),
86 ProgramError::IncorrectAuthority => to_builtin(24),
87 }
88 }
89}
90
91impl From<u64> for ProgramError {
92 fn from(code: u64) -> Self {
93 if code == CUSTOM_ZERO {
94 return ProgramError::Custom(0);
95 }
96 let builtin = code >> BUILTIN_BIT_SHIFT;
97 if code & BUILTIN_LOW_MASK == 0 && builtin >= 2 {
98 match builtin - 2 {
99 0 => return ProgramError::InvalidArgument,
100 1 => return ProgramError::InvalidInstructionData,
101 2 => return ProgramError::InvalidAccountData,
102 3 => return ProgramError::AccountDataTooSmall,
103 4 => return ProgramError::InsufficientFunds,
104 5 => return ProgramError::IncorrectProgramId,
105 6 => return ProgramError::MissingRequiredSignature,
106 7 => return ProgramError::AccountAlreadyInitialized,
107 8 => return ProgramError::UninitializedAccount,
108 9 => return ProgramError::NotEnoughAccountKeys,
109 10 => return ProgramError::AccountBorrowFailed,
110 11 => return ProgramError::MaxSeedLengthExceeded,
111 12 => return ProgramError::InvalidSeeds,
112 13 => return ProgramError::BorshIoError,
113 14 => return ProgramError::AccountNotRentExempt,
114 15 => return ProgramError::UnsupportedSysvar,
115 16 => return ProgramError::IllegalOwner,
116 17 => return ProgramError::MaxAccountsDataAllocationsExceeded,
117 18 => return ProgramError::InvalidRealloc,
118 19 => return ProgramError::MaxInstructionTraceLengthExceeded,
119 20 => return ProgramError::BuiltinProgramsMustConsumeComputeUnits,
120 21 => return ProgramError::InvalidAccountOwner,
121 22 => return ProgramError::ArithmeticOverflow,
122 23 => return ProgramError::Immutable,
123 24 => return ProgramError::IncorrectAuthority,
124 _ => {}
125 }
126 }
127 ProgramError::Custom(code as u32)
128 }
129}
130
131impl core::fmt::Display for ProgramError {
132 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
133 match self {
134 ProgramError::Custom(code) => write!(f, "Custom({code})"),
135 ProgramError::InvalidArgument => write!(f, "InvalidArgument"),
136 ProgramError::InvalidInstructionData => write!(f, "InvalidInstructionData"),
137 ProgramError::InvalidAccountData => write!(f, "InvalidAccountData"),
138 ProgramError::AccountDataTooSmall => write!(f, "AccountDataTooSmall"),
139 ProgramError::InsufficientFunds => write!(f, "InsufficientFunds"),
140 ProgramError::IncorrectProgramId => write!(f, "IncorrectProgramId"),
141 ProgramError::MissingRequiredSignature => write!(f, "MissingRequiredSignature"),
142 ProgramError::AccountAlreadyInitialized => write!(f, "AccountAlreadyInitialized"),
143 ProgramError::UninitializedAccount => write!(f, "UninitializedAccount"),
144 ProgramError::NotEnoughAccountKeys => write!(f, "NotEnoughAccountKeys"),
145 ProgramError::AccountBorrowFailed => write!(f, "AccountBorrowFailed"),
146 ProgramError::MaxSeedLengthExceeded => write!(f, "MaxSeedLengthExceeded"),
147 ProgramError::InvalidSeeds => write!(f, "InvalidSeeds"),
148 ProgramError::BorshIoError => write!(f, "BorshIoError"),
149 ProgramError::AccountNotRentExempt => write!(f, "AccountNotRentExempt"),
150 ProgramError::UnsupportedSysvar => write!(f, "UnsupportedSysvar"),
151 ProgramError::IllegalOwner => write!(f, "IllegalOwner"),
152 ProgramError::MaxAccountsDataAllocationsExceeded => {
153 write!(f, "MaxAccountsDataAllocationsExceeded")
154 }
155 ProgramError::InvalidRealloc => write!(f, "InvalidRealloc"),
156 ProgramError::MaxInstructionTraceLengthExceeded => {
157 write!(f, "MaxInstructionTraceLengthExceeded")
158 }
159 ProgramError::BuiltinProgramsMustConsumeComputeUnits => {
160 write!(f, "BuiltinProgramsMustConsumeComputeUnits")
161 }
162 ProgramError::InvalidAccountOwner => write!(f, "InvalidAccountOwner"),
163 ProgramError::ArithmeticOverflow => write!(f, "ArithmeticOverflow"),
164 ProgramError::Immutable => write!(f, "Immutable"),
165 ProgramError::IncorrectAuthority => write!(f, "IncorrectAuthority"),
166 }
167 }
168}
169
170#[cfg(feature = "hopper-native-backend")]
178impl From<hopper_native::error::ProgramError> for ProgramError {
179 #[inline]
180 fn from(e: hopper_native::error::ProgramError) -> Self {
181 match e {
182 hopper_native::error::ProgramError::Custom(code) => ProgramError::Custom(code),
183 hopper_native::error::ProgramError::InvalidArgument => ProgramError::InvalidArgument,
184 hopper_native::error::ProgramError::InvalidInstructionData => {
185 ProgramError::InvalidInstructionData
186 }
187 hopper_native::error::ProgramError::InvalidAccountData => {
188 ProgramError::InvalidAccountData
189 }
190 hopper_native::error::ProgramError::AccountDataTooSmall => {
191 ProgramError::AccountDataTooSmall
192 }
193 hopper_native::error::ProgramError::InsufficientFunds => {
194 ProgramError::InsufficientFunds
195 }
196 hopper_native::error::ProgramError::IncorrectProgramId => {
197 ProgramError::IncorrectProgramId
198 }
199 hopper_native::error::ProgramError::MissingRequiredSignature => {
200 ProgramError::MissingRequiredSignature
201 }
202 hopper_native::error::ProgramError::AccountAlreadyInitialized => {
203 ProgramError::AccountAlreadyInitialized
204 }
205 hopper_native::error::ProgramError::UninitializedAccount => {
206 ProgramError::UninitializedAccount
207 }
208 hopper_native::error::ProgramError::NotEnoughAccountKeys => {
209 ProgramError::NotEnoughAccountKeys
210 }
211 hopper_native::error::ProgramError::AccountBorrowFailed => {
212 ProgramError::AccountBorrowFailed
213 }
214 hopper_native::error::ProgramError::MaxSeedLengthExceeded => {
215 ProgramError::MaxSeedLengthExceeded
216 }
217 hopper_native::error::ProgramError::InvalidSeeds => ProgramError::InvalidSeeds,
218 hopper_native::error::ProgramError::BorshIoError => ProgramError::BorshIoError,
219 hopper_native::error::ProgramError::AccountNotRentExempt => {
220 ProgramError::AccountNotRentExempt
221 }
222 hopper_native::error::ProgramError::UnsupportedSysvar => {
223 ProgramError::UnsupportedSysvar
224 }
225 hopper_native::error::ProgramError::IllegalOwner => ProgramError::IllegalOwner,
226 hopper_native::error::ProgramError::MaxAccountsDataAllocationsExceeded => {
227 ProgramError::MaxAccountsDataAllocationsExceeded
228 }
229 hopper_native::error::ProgramError::InvalidRealloc => ProgramError::InvalidRealloc,
230 hopper_native::error::ProgramError::MaxInstructionTraceLengthExceeded => {
231 ProgramError::MaxInstructionTraceLengthExceeded
232 }
233 hopper_native::error::ProgramError::BuiltinProgramsMustConsumeComputeUnits => {
234 ProgramError::BuiltinProgramsMustConsumeComputeUnits
235 }
236 hopper_native::error::ProgramError::InvalidAccountOwner => {
237 ProgramError::InvalidAccountOwner
238 }
239 hopper_native::error::ProgramError::ArithmeticOverflow => {
240 ProgramError::ArithmeticOverflow
241 }
242 hopper_native::error::ProgramError::Immutable => ProgramError::Immutable,
243 hopper_native::error::ProgramError::IncorrectAuthority => {
244 ProgramError::IncorrectAuthority
245 }
246 }
247 }
248}
249
250#[cfg(feature = "hopper-native-backend")]
251impl From<ProgramError> for hopper_native::error::ProgramError {
252 #[inline]
253 fn from(e: ProgramError) -> Self {
254 match e {
255 ProgramError::Custom(code) => hopper_native::error::ProgramError::Custom(code),
256 ProgramError::InvalidArgument => hopper_native::error::ProgramError::InvalidArgument,
257 ProgramError::InvalidInstructionData => {
258 hopper_native::error::ProgramError::InvalidInstructionData
259 }
260 ProgramError::InvalidAccountData => {
261 hopper_native::error::ProgramError::InvalidAccountData
262 }
263 ProgramError::AccountDataTooSmall => {
264 hopper_native::error::ProgramError::AccountDataTooSmall
265 }
266 ProgramError::InsufficientFunds => {
267 hopper_native::error::ProgramError::InsufficientFunds
268 }
269 ProgramError::IncorrectProgramId => {
270 hopper_native::error::ProgramError::IncorrectProgramId
271 }
272 ProgramError::MissingRequiredSignature => {
273 hopper_native::error::ProgramError::MissingRequiredSignature
274 }
275 ProgramError::AccountAlreadyInitialized => {
276 hopper_native::error::ProgramError::AccountAlreadyInitialized
277 }
278 ProgramError::UninitializedAccount => {
279 hopper_native::error::ProgramError::UninitializedAccount
280 }
281 ProgramError::NotEnoughAccountKeys => {
282 hopper_native::error::ProgramError::NotEnoughAccountKeys
283 }
284 ProgramError::AccountBorrowFailed => {
285 hopper_native::error::ProgramError::AccountBorrowFailed
286 }
287 ProgramError::MaxSeedLengthExceeded => {
288 hopper_native::error::ProgramError::MaxSeedLengthExceeded
289 }
290 ProgramError::InvalidSeeds => hopper_native::error::ProgramError::InvalidSeeds,
291 ProgramError::BorshIoError => hopper_native::error::ProgramError::BorshIoError,
292 ProgramError::AccountNotRentExempt => {
293 hopper_native::error::ProgramError::AccountNotRentExempt
294 }
295 ProgramError::UnsupportedSysvar => {
296 hopper_native::error::ProgramError::UnsupportedSysvar
297 }
298 ProgramError::IllegalOwner => hopper_native::error::ProgramError::IllegalOwner,
299 ProgramError::MaxAccountsDataAllocationsExceeded => {
300 hopper_native::error::ProgramError::MaxAccountsDataAllocationsExceeded
301 }
302 ProgramError::InvalidRealloc => hopper_native::error::ProgramError::InvalidRealloc,
303 ProgramError::MaxInstructionTraceLengthExceeded => {
304 hopper_native::error::ProgramError::MaxInstructionTraceLengthExceeded
305 }
306 ProgramError::BuiltinProgramsMustConsumeComputeUnits => {
307 hopper_native::error::ProgramError::BuiltinProgramsMustConsumeComputeUnits
308 }
309 ProgramError::InvalidAccountOwner => {
310 hopper_native::error::ProgramError::InvalidAccountOwner
311 }
312 ProgramError::ArithmeticOverflow => {
313 hopper_native::error::ProgramError::ArithmeticOverflow
314 }
315 ProgramError::Immutable => hopper_native::error::ProgramError::Immutable,
316 ProgramError::IncorrectAuthority => {
317 hopper_native::error::ProgramError::IncorrectAuthority
318 }
319 }
320 }
321}
322
323impl ProgramError {
332 #[inline(always)]
333 pub fn err_data_too_small<T>() -> Result<T, Self> {
334 Err(ProgramError::AccountDataTooSmall)
335 }
336
337 #[cold]
338 #[inline(never)]
339 pub fn err_invalid_data<T>() -> Result<T, Self> {
340 Err(ProgramError::InvalidAccountData)
341 }
342
343 #[cold]
344 #[inline(never)]
345 pub fn err_missing_signer<T>() -> Result<T, Self> {
346 Err(ProgramError::MissingRequiredSignature)
347 }
348
349 #[inline(always)]
350 pub fn err_immutable<T>() -> Result<T, Self> {
351 Err(ProgramError::Immutable)
352 }
353
354 #[cold]
355 #[inline(never)]
356 pub fn err_not_enough_keys<T>() -> Result<T, Self> {
357 Err(ProgramError::NotEnoughAccountKeys)
358 }
359
360 #[cold]
361 #[inline(never)]
362 pub fn err_borrow_failed<T>() -> Result<T, Self> {
363 Err(ProgramError::AccountBorrowFailed)
364 }
365
366 #[cold]
367 #[inline(never)]
368 pub fn err_overflow<T>() -> Result<T, Self> {
369 Err(ProgramError::ArithmeticOverflow)
370 }
371
372 #[cold]
373 #[inline(never)]
374 pub fn err_invalid_argument<T>() -> Result<T, Self> {
375 Err(ProgramError::InvalidArgument)
376 }
377
378 #[inline(always)]
379 pub fn err_incorrect_program<T>() -> Result<T, Self> {
380 Err(ProgramError::IncorrectProgramId)
381 }
382}