|
1 | 1 | use crate::{Error, Result}; |
| 2 | +use alloy_dyn_abi::{DynSolValue, ErrorExt}; |
2 | 3 | use alloy_primitives::{Address, Bytes, address, hex}; |
3 | 4 | use alloy_sol_types::{SolError, SolValue}; |
4 | | -use foundry_common::ContractsByArtifact; |
| 5 | +use foundry_common::{ContractsByArtifact, abi::get_error}; |
5 | 6 | use foundry_evm_core::decode::RevertDecoder; |
6 | 7 | use revm::interpreter::{InstructionResult, return_ok}; |
7 | 8 | use spec::Vm; |
@@ -96,24 +97,34 @@ fn handle_revert( |
96 | 97 | if actual_revert == expected_reason |
97 | 98 | || (is_cheatcode && memchr::memmem::find(&actual_revert, expected_reason).is_some()) |
98 | 99 | { |
99 | | - Ok(()) |
100 | | - } else { |
101 | | - let (actual, expected) = if let Some(contracts) = known_contracts { |
102 | | - let decoder = RevertDecoder::new().with_abis(contracts.values().map(|c| &c.abi)); |
103 | | - ( |
104 | | - &decoder.decode(actual_revert.as_slice(), Some(status)), |
105 | | - &decoder.decode(expected_reason, Some(status)), |
106 | | - ) |
107 | | - } else { |
108 | | - (&stringify(&actual_revert), &stringify(expected_reason)) |
109 | | - }; |
| 100 | + return Ok(()); |
| 101 | + } |
110 | 102 |
|
111 | | - if expected == actual { |
112 | | - return Ok(()); |
113 | | - } |
| 103 | + // If expected reason is `Error(string)` then decode and compare with actual revert. |
| 104 | + // See <https://github.com/foundry-rs/foundry/issues/12511> |
| 105 | + if let Ok(e) = get_error("Error(string)") |
| 106 | + && let Ok(dec) = e.decode_error(expected_reason) |
| 107 | + && let Some(DynSolValue::String(revert_str)) = dec.body.first() |
| 108 | + && revert_str.as_str() == String::from_utf8_lossy(&actual_revert) |
| 109 | + { |
| 110 | + return Ok(()); |
| 111 | + } |
114 | 112 |
|
115 | | - Err(fmt_err!("Error != expected error: {} != {}", actual, expected)) |
| 113 | + let (actual, expected) = if let Some(contracts) = known_contracts { |
| 114 | + let decoder = RevertDecoder::new().with_abis(contracts.values().map(|c| &c.abi)); |
| 115 | + ( |
| 116 | + &decoder.decode(actual_revert.as_slice(), Some(status)), |
| 117 | + &decoder.decode(expected_reason, Some(status)), |
| 118 | + ) |
| 119 | + } else { |
| 120 | + (&stringify(&actual_revert), &stringify(expected_reason)) |
| 121 | + }; |
| 122 | + |
| 123 | + if expected == actual { |
| 124 | + return Ok(()); |
116 | 125 | } |
| 126 | + |
| 127 | + Err(fmt_err!("Error != expected error: {} != {}", actual, expected)) |
117 | 128 | } |
118 | 129 |
|
119 | 130 | pub(crate) fn handle_assume_no_revert( |
|
0 commit comments