Skip to content

Commit

Permalink
Merge pull request #14590 from ethereum/severity-and-color-for-cli-er…
Browse files Browse the repository at this point in the history
…ror-messages

Consistent severity and color for CLI error messages
  • Loading branch information
cameel authored Oct 17, 2023
2 parents e98f174 + 23b7505 commit 766efb3
Show file tree
Hide file tree
Showing 55 changed files with 138 additions and 79 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Language Features:


Compiler Features:
* Commandline Interface: Use proper severity and coloring also for error messages produced outside of the compilation pipeline.
* Parser: Remove the experimental error recovery mode (``--error-recovery`` / ``settings.parserErrorRecovery``).
* Yul Optimizer: If ``PUSH0`` is supported, favor zero literals over storing zero values in variables.
* Yul Optimizer: Run the ``Rematerializer`` and ``UnusedPruner`` steps at the end of the default clean-up sequence.
Expand Down
30 changes: 21 additions & 9 deletions liblangutil/SourceReferenceFormatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ AnsiColorized SourceReferenceFormatter::frameColored() const
return AnsiColorized(m_stream, m_colored, {BOLD, BLUE});
}

AnsiColorized SourceReferenceFormatter::errorColored(Error::Severity _severity) const
AnsiColorized SourceReferenceFormatter::errorColored(std::ostream& _stream, bool _colored, Error::Severity _severity)
{
// We used to color messages of any severity as errors so this seems like a good default
// for cases where severity cannot be determined.
Expand All @@ -78,12 +78,12 @@ AnsiColorized SourceReferenceFormatter::errorColored(Error::Severity _severity)
case Error::Severity::Info: textColor = WHITE; break;
}

return AnsiColorized(m_stream, m_colored, {BOLD, textColor});
return AnsiColorized(_stream, _colored, {BOLD, textColor});
}

AnsiColorized SourceReferenceFormatter::messageColored() const
AnsiColorized SourceReferenceFormatter::messageColored(std::ostream& _stream, bool _colored)
{
return AnsiColorized(m_stream, m_colored, {BOLD, WHITE});
return AnsiColorized(_stream, _colored, {BOLD, WHITE});
}

AnsiColorized SourceReferenceFormatter::secondaryColored() const
Expand Down Expand Up @@ -175,14 +175,26 @@ void SourceReferenceFormatter::printSourceLocation(SourceReference const& _ref)
}
}

void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)
void SourceReferenceFormatter::printPrimaryMessage(
std::ostream& _stream,
std::string _message,
std::variant<Error::Type, Error::Severity> _typeOrSeverity,
std::optional<ErrorId> _errorId,
bool _colored,
bool _withErrorIds
)
{
errorColored(Error::errorSeverityOrType(_msg._typeOrSeverity)) << Error::formatTypeOrSeverity(_msg._typeOrSeverity);
errorColored(_stream, _colored, Error::errorSeverityOrType(_typeOrSeverity)) << Error::formatTypeOrSeverity(_typeOrSeverity);

if (_withErrorIds && _errorId.has_value())
errorColored(_stream, _colored, Error::errorSeverityOrType(_typeOrSeverity)) << " (" << _errorId.value().error << ")";

if (m_withErrorIds && _msg.errorId.has_value())
errorColored(Error::errorSeverityOrType(_msg._typeOrSeverity)) << " (" << _msg.errorId.value().error << ")";
messageColored(_stream, _colored) << ": " << _message << '\n';
}

messageColored() << ": " << _msg.primary.message << '\n';
void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)
{
printPrimaryMessage(m_stream, _msg.primary.message, _msg._typeOrSeverity, _msg.errorId, m_colored, m_withErrorIds);
printSourceLocation(_msg.primary);

for (auto const& secondary: _msg.secondary)
Expand Down
16 changes: 14 additions & 2 deletions liblangutil/SourceReferenceFormatter.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,27 @@ class SourceReferenceFormatter

static std::string formatErrorInformation(Error const& _error, CharStream const& _charStream);

static void printPrimaryMessage(
std::ostream& _stream,
std::string _message,
std::variant<Error::Type, Error::Severity> _typeOrSeverity,
std::optional<ErrorId> _errorId = std::nullopt,
bool _colored = false,
bool _withErrorIds = false
);

private:
util::AnsiColorized normalColored() const;
util::AnsiColorized frameColored() const;
util::AnsiColorized errorColored(langutil::Error::Severity _severity) const;
util::AnsiColorized messageColored() const;
util::AnsiColorized errorColored(Error::Severity _severity) const { return errorColored(m_stream, m_colored, _severity); }
util::AnsiColorized messageColored() const { return messageColored(m_stream, m_colored); }
util::AnsiColorized secondaryColored() const;
util::AnsiColorized highlightColored() const;
util::AnsiColorized diagColored() const;

static util::AnsiColorized errorColored(std::ostream& _stream, bool _colored, langutil::Error::Severity _severity);
static util::AnsiColorized messageColored(std::ostream& _stream, bool _colored);

private:
std::ostream& m_stream;
CharStreamProvider const& m_charStreamProvider;
Expand Down
43 changes: 35 additions & 8 deletions solc/CommandLineInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ void CommandLineInterface::readInputFiles()
if (!m_options.input.ignoreMissingFiles)
solThrow(CommandLineValidationError, '"' + infile.string() + "\" is not found.");
else
serr() << infile << " is not found. Skipping." << std::endl;
report(Error::Severity::Info, fmt::format("\"{}\" is not found. Skipping.", infile.string()));

continue;
}
Expand All @@ -527,7 +527,7 @@ void CommandLineInterface::readInputFiles()
if (!m_options.input.ignoreMissingFiles)
solThrow(CommandLineValidationError, '"' + infile.string() + "\" is not a valid file.");
else
serr() << infile << " is not a valid file. Skipping." << std::endl;
report(Error::Severity::Info, fmt::format("\"{}\" is not a valid file. Skipping.", infile.string()));

continue;
}
Expand Down Expand Up @@ -639,7 +639,7 @@ bool CommandLineInterface::run(int _argc, char const* const* _argv)
// There might be no message in the exception itself if the error output is bulky and has
// already been printed to stderr (this happens e.g. for compiler errors).
if (_exception.what() != ""s)
serr() << _exception.what() << std::endl;
report(Error::Severity::Error, _exception.what());

return false;
}
Expand All @@ -658,7 +658,19 @@ bool CommandLineInterface::parseArguments(int _argc, char const* const* _argv)
return false;
}

parser.parse(_argc, _argv);
try
{
parser.parse(_argc, _argv);
}
catch (...)
{
// Even if the overall CLI parsing fails, the --color/--no-color options may have been
// successfully parsed, and if so, should be taken into account when printing errors.
// If no value is present, it's possible that --no-color is still there but parsing failed
// due to other, unrecognized options so play it safe and disable color in that case.
m_options.formatting.coloredOutput = parser.options().formatting.coloredOutput.value_or(false);
throw;
}
m_options = parser.options();

return true;
Expand Down Expand Up @@ -817,7 +829,7 @@ void CommandLineInterface::compile()
{
if (_error.type() == Error::Type::DocstringParsingError)
{
serr() << *boost::get_error_info<errinfo_comment>(_error);
report(Error::Severity::Error, *boost::get_error_info<errinfo_comment>(_error));
solThrow(CommandLineExecutionError, "Documentation parsing failed.");
}
else
Expand Down Expand Up @@ -1020,7 +1032,10 @@ void CommandLineInterface::link()
copy(hexStr.begin(), hexStr.end(), it);
}
else
serr() << "Reference \"" << foundPlaceholder << "\" in file \"" << src.first << "\" still unresolved." << std::endl;
report(
Error::Severity::Warning,
fmt::format("Reference \"{}\" in file \"{}\" still unresolved.", foundPlaceholder, src.first)
);
it += placeholderSize;
}
// Remove hints for resolved libraries.
Expand Down Expand Up @@ -1136,7 +1151,7 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
if (object.bytecode)
sout() << object.bytecode->toHex() << std::endl;
else
serr() << "No binary representation found." << std::endl;
report(Error::Severity::Info, "No binary representation found.");
}
if (m_options.compiler.outputs.astCompactJson)
{
Expand All @@ -1150,7 +1165,7 @@ void CommandLineInterface::assembleYul(yul::YulStack::Language _language, yul::Y
if (!object.assembly.empty())
sout() << object.assembly << std::endl;
else
serr() << "No text representation found." << std::endl;
report(Error::Severity::Info, "No text representation found.");
}
}
}
Expand Down Expand Up @@ -1220,4 +1235,16 @@ void CommandLineInterface::outputCompilationResults()
}
}

void CommandLineInterface::report(langutil::Error::Severity _severity, std::string _message)
{
SourceReferenceFormatter::printPrimaryMessage(
serr(),
_message,
_severity,
std::nullopt,
coloredOutput(m_options),
m_options.formatting.withErrorIds
);
}

}
2 changes: 2 additions & 0 deletions solc/CommandLineInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ class CommandLineInterface
/// stream has ever been used unless @arg _markAsUsed is set to false.
std::ostream& serr(bool _markAsUsed = true);

void report(langutil::Error::Severity _severity, std::string _message);

std::istream& m_sin;
std::ostream& m_sout;
std::ostream& m_serr;
Expand Down
13 changes: 8 additions & 5 deletions solc/CommandLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,9 @@ void CommandLineParser::parseArgs(int _argc, char const* const* _argv)
po::options_description allOptions = optionsDescription();
po::positional_options_description filesPositions = positionalOptionsDescription();

m_options = {};
m_args = {};

// parse the compiler arguments
try
{
Expand All @@ -914,6 +917,11 @@ void CommandLineParser::parseArgs(int _argc, char const* const* _argv)

void CommandLineParser::processArgs()
{
if (m_args.count(g_strNoColor) > 0)
m_options.formatting.coloredOutput = false;
else if (m_args.count(g_strColor) > 0)
m_options.formatting.coloredOutput = true;

checkMutuallyExclusive({
g_strHelp,
g_strLicense,
Expand Down Expand Up @@ -1028,11 +1036,6 @@ void CommandLineParser::processArgs()
);
}

if (m_args.count(g_strColor) > 0)
m_options.formatting.coloredOutput = true;
else if (m_args.count(g_strNoColor) > 0)
m_options.formatting.coloredOutput = false;

m_options.formatting.withErrorIds = m_args.count(g_strErrorIds);

if (m_args.count(g_strRevertStrings))
Expand Down
8 changes: 4 additions & 4 deletions test/cmdlineTests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -318,14 +318,14 @@ EOF
## RUN

printTask "Testing passing files that are not found..."
test_solc_behaviour "file_not_found.sol" "" "" "" 1 "" "\"file_not_found.sol\" is not found." "" ""
test_solc_behaviour "file_not_found.sol" "" "" "" 1 "" "Error: \"file_not_found.sol\" is not found." "" ""

printTask "Testing passing files that are not files..."
test_solc_behaviour "." "" "" "" 1 "" "\".\" is not a valid file." "" ""
test_solc_behaviour "." "" "" "" 1 "" "Error: \".\" is not a valid file." "" ""

printTask "Testing passing empty remappings..."
test_solc_behaviour "${0}" "=/some/remapping/target" "" "" 1 "" "Invalid remapping: \"=/some/remapping/target\"." "" ""
test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" "" 1 "" "Invalid remapping: \"ctx:=/some/remapping/target\"." "" ""
test_solc_behaviour "${0}" "=/some/remapping/target" "" "" 1 "" "Error: Invalid remapping: \"=/some/remapping/target\"." "" ""
test_solc_behaviour "${0}" "ctx:=/some/remapping/target" "" "" 1 "" "Error: Invalid remapping: \"ctx:=/some/remapping/target\"." "" ""

printTask "Running general commandline tests..."
(
Expand Down
2 changes: 1 addition & 1 deletion test/cmdlineTests/ast_json_import_wrong_evmVersion/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Failed to import AST: Imported tree evm version differs from configured evm version!
Error: Failed to import AST: Imported tree evm version differs from configured evm version!
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid value for --debug-info option: location,all,none
Error: Invalid value for --debug-info option: location,all,none
Original file line number Diff line number Diff line change
@@ -1 +1 @@
To use 'snippet' with --debug-info you must select also 'location'.
Error: To use 'snippet' with --debug-info you must select also 'location'.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --no-optimize-yul is only valid in compiler and assembler modes.
Error: Option --no-optimize-yul is only valid in compiler and assembler modes.
2 changes: 1 addition & 1 deletion test/cmdlineTests/linker_mode_invalid_option_optimize/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize is only valid in compiler and assembler modes.
Error: Option --optimize is only valid in compiler and assembler modes.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize-runs is only valid in compiler and assembler modes.
Error: Option --optimize-runs is only valid in compiler and assembler modes.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize-yul is only valid in compiler and assembler modes.
Error: Option --optimize-yul is only valid in compiler and assembler modes.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --yul-optimizations is only valid in compiler and assembler modes.
Error: Option --yul-optimizations is only valid in compiler and assembler modes.
2 changes: 1 addition & 1 deletion test/cmdlineTests/linker_mode_output_selection_invalid/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The following outputs are not supported in linker mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
Error: The following outputs are not supported in linker mode: --abi, --asm, --asm-json, --bin, --bin-runtime, --devdoc, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Address specified more than once for library "library.sol:L".
Error: Address specified more than once for library "library.sol:L".
Original file line number Diff line number Diff line change
@@ -1 +1 @@
the argument ('bmc') for option '--model-checker-bmc-loop-iterations' is invalid
Error: the argument ('bmc') for option '--model-checker-bmc-loop-iterations' is invalid
Original file line number Diff line number Diff line change
@@ -1 +1 @@
the argument ('model_checker_bmc_loop_iterations_no_argument/input.sol') for option '--model-checker-bmc-loop-iterations' is invalid
Error: the argument ('model_checker_bmc_loop_iterations_no_argument/input.sol') for option '--model-checker-bmc-loop-iterations' is invalid
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-contracts: model_checker_contracts_inexistent_contract/input.sol:
Error: Invalid option for --model-checker-contracts: model_checker_contracts_inexistent_contract/input.sol:
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-contracts: a.sol:
Error: Invalid option for --model-checker-contracts: a.sol:
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_contracts_empty_source/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-contracts: :A
Error: Invalid option for --model-checker-contracts: :A
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-contracts: model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A
Error: Invalid option for --model-checker-contracts: model_checker_contracts_all_explicit/input.sol:,model_checker_contracts_all_explicit/input.sol:A
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-contracts: :C
Error: Invalid option for --model-checker-contracts: :C
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_ext_calls_empty_arg/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
No input files given. If you wish to use the standard input please specify "-" explicitly.
Error: No input files given. If you wish to use the standard input please specify "-" explicitly.
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_ext_calls_wrong_arg/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-ext-calls: what
Error: Invalid option for --model-checker-ext-calls: what
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_invariants_wrong/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-invariants: what
Error: Invalid option for --model-checker-invariants: what
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Only SMTLib2 solver can be enabled to print queries
Error: Only SMTLib2 solver can be enabled to print queries
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Only SMTLib2 solver can be enabled to print queries
Error: Only SMTLib2 solver can be enabled to print queries
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Only SMTLib2 solver can be enabled to print queries
Error: Only SMTLib2 solver can be enabled to print queries
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_solvers_wrong/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-solvers: ultraSolver
Error: Invalid option for --model-checker-solvers: ultraSolver
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_solvers_wrong2/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"smtlib2" is not found.
Error: "smtlib2" is not found.
2 changes: 1 addition & 1 deletion test/cmdlineTests/model_checker_targets_error/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid option for --model-checker-targets: aaa,bbb
Error: Invalid option for --model-checker-targets: aaa,bbb
2 changes: 1 addition & 1 deletion test/cmdlineTests/no_cbor_metadata_with_metadata_hash/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Cannot specify a metadata hashing method when --no-cbor-metadata is set.
Error: Cannot specify a metadata hashing method when --no-cbor-metadata is set.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Options --optimize-yul and --no-optimize-yul cannot be used together.
Error: Options --optimize-yul and --no-optimize-yul cannot be used together.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
Error: The following outputs are not supported in standard JSON mode: --abi, --asm, --asm-json, --ast-compact-json, --bin, --bin-runtime, --devdoc, --hashes, --ir, --ir-optimized, --metadata, --opcodes, --storage-layout, --userdoc.
2 changes: 1 addition & 1 deletion test/cmdlineTests/standard_file_not_found/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"input.sol" is not found.
Error: "input.sol" is not found.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --no-optimize-yul is only valid in compiler and assembler modes.
Error: Option --no-optimize-yul is only valid in compiler and assembler modes.
2 changes: 1 addition & 1 deletion test/cmdlineTests/standard_invalid_option_optimize/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize is only valid in compiler and assembler modes.
Error: Option --optimize is only valid in compiler and assembler modes.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize-runs is only valid in compiler and assembler modes.
Error: Option --optimize-runs is only valid in compiler and assembler modes.
2 changes: 1 addition & 1 deletion test/cmdlineTests/standard_invalid_option_optimize_yul/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --optimize-yul is only valid in compiler and assembler modes.
Error: Option --optimize-yul is only valid in compiler and assembler modes.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Option --yul-optimizations is only valid in compiler and assembler modes.
Error: Option --yul-optimizations is only valid in compiler and assembler modes.
2 changes: 1 addition & 1 deletion test/cmdlineTests/stop_after_parsing_abi/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The following options are mutually exclusive: --stop-after, --abi. Select at most one.
Error: The following options are mutually exclusive: --stop-after, --abi. Select at most one.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
To use 'snippet' with --debug-info you must select also 'location'.
Error: To use 'snippet' with --debug-info you must select also 'location'.
2 changes: 1 addition & 1 deletion test/cmdlineTests/strict_asm_invalid_option_output_dir/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The following options are invalid in assembly mode: --output-dir.
Error: The following options are invalid in assembly mode: --output-dir.
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Options --optimize-yul and --no-optimize-yul cannot be used together.
Error: Options --optimize-yul and --no-optimize-yul cannot be used together.
2 changes: 1 addition & 1 deletion test/cmdlineTests/strict_asm_options_in_non_asm_mode/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
--yul-dialect and --machine are only valid in assembly mode.
Error: --yul-dialect and --machine are only valid in assembly mode.
2 changes: 1 addition & 1 deletion test/cmdlineTests/strict_asm_output_selection_invalid/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
The following outputs are not supported in assembler mode: --abi, --asm-json, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc.
Error: The following outputs are not supported in assembler mode: --abi, --asm-json, --bin-runtime, --devdoc, --hashes, --ir, --metadata, --opcodes, --storage-layout, --userdoc.
2 changes: 1 addition & 1 deletion test/cmdlineTests/yul_optimizer_steps_disabled/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
--yul-optimizations is invalid if Yul optimizer is disabled
Error: --yul-optimizations is invalid if Yul optimizer is disabled
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid optimizer step sequence in --yul-optimizations: 'b' is not a valid step abbreviation
Error: Invalid optimizer step sequence in --yul-optimizations: 'b' is not a valid step abbreviation
2 changes: 1 addition & 1 deletion test/cmdlineTests/yul_optimizer_steps_nesting_too_deep/err
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid optimizer step sequence in --yul-optimizations: Brackets nested too deep
Error: Invalid optimizer step sequence in --yul-optimizations: Brackets nested too deep
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid optimizer step sequence in --yul-optimizations: Unbalanced brackets
Error: Invalid optimizer step sequence in --yul-optimizations: Unbalanced brackets
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invalid optimizer step sequence in --yul-optimizations: Unbalanced brackets
Error: Invalid optimizer step sequence in --yul-optimizations: Unbalanced brackets
Loading

0 comments on commit 766efb3

Please sign in to comment.