diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt
index 03dfd1e9e90f..18dbb87d20f0 100644
--- a/libsolidity/CMakeLists.txt
+++ b/libsolidity/CMakeLists.txt
@@ -161,6 +161,10 @@ set(sources
interface/SMTSolverCommand.h
interface/StandardCompiler.cpp
interface/StandardCompiler.h
+ interface/StandardJSONInput.h
+ interface/StandardJSONInput.cpp
+ interface/StandardJSONOutput.h
+ interface/StandardJSONOutput.cpp
interface/StorageLayout.cpp
interface/StorageLayout.h
interface/UniversalCallback.h
diff --git a/libsolidity/interface/StandardJSONInput.cpp b/libsolidity/interface/StandardJSONInput.cpp
new file mode 100644
index 000000000000..e2e9c67526f0
--- /dev/null
+++ b/libsolidity/interface/StandardJSONInput.cpp
@@ -0,0 +1,131 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+// SPDX-License-Identifier: GPL-3.0
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+using namespace solidity::frontend;
+using namespace solidity::frontend::json;
+using namespace solidity::frontend::json::input;
+
+void input::to_json(Json& _json, YulOptimizerDetails const& _details)
+{
+ if (_details.stackAllocation)
+ _json["stackAllocation"] = *_details.stackAllocation;
+ if (_details.optimizerSteps)
+ _json["optimizerSteps"] = *_details.optimizerSteps;
+}
+
+void input::to_json(Json& _json, OptimizerDetails const& _details)
+{
+ if (_details.peephole)
+ _json["peephole"] = *_details.peephole;
+ if (_details.orderLiterals)
+ _json["orderLiterals"] = *_details.orderLiterals;
+ if (_details.inliner)
+ _json["inliner"] = *_details.inliner;
+ if (_details.jumpdestRemover)
+ _json["jumpdestRemover"] = *_details.jumpdestRemover;
+ if (_details.deduplicate)
+ _json["deduplicate"] = *_details.deduplicate;
+ if (_details.cse)
+ _json["cse"] = *_details.cse;
+ if (_details.constantOptimizer)
+ _json["constantOptimizer"] = *_details.constantOptimizer;
+ if (_details.simpleCounterForLoopUncheckedIncrement)
+ _json["simpleCounterForLoopUncheckedIncrement"] = *_details.simpleCounterForLoopUncheckedIncrement;
+ if (_details.yul)
+ _json["yul"] = *_details.yul;
+ if (_details.yulDetails && _details.yul && *_details.yul)
+ _json["yulDetails"] = *_details.yulDetails;
+}
+
+void input::to_json(Json& _json, Optimizer const& _optimizer)
+{
+ if (_optimizer.enable)
+ _json["enabled"] = *_optimizer.enable;
+ if (_optimizer.runs)
+ _json["runs"] = *_optimizer.runs;
+ if (_optimizer.details)
+ _json["details"] = *_optimizer.details;
+}
+
+void input::to_json(Json& _json, Debug const& _debug)
+{
+ if (_debug.revertStrings)
+ _json["revertStrings"] = revertStringsToString(_debug.revertStrings.value());
+}
+
+void input::to_json(Json& _json, Metadata const& _metadata)
+{
+ if (_metadata.appendCBOR)
+ {
+ _json["appendCBOR"] = *_metadata.appendCBOR;
+ if (*_metadata.appendCBOR && _metadata.bytecodeHash)
+ _json["bytecodeHash"] = metadataHashToString(_metadata.bytecodeHash.value());
+ }
+}
+
+void input::to_json(Json& _json, Settings const& _settings)
+{
+ if (_settings.optimizer)
+ _json["optimizer"] = *_settings.optimizer;
+ if (_settings.evmVersion)
+ _json["evmVersion"] = (*_settings.evmVersion).name();
+ if (_settings.eofVersion)
+ _json["eofVersion"] = *_settings.eofVersion;
+ if (_settings.viaIR)
+ _json["viaIR"] = *_settings.viaIR;
+ if (_settings.viaSSACFG)
+ _json["viaSSACFG"] = *_settings.viaSSACFG;
+ if (_settings.debug)
+ _json["debug"] = *_settings.debug;
+ if (_settings.metadata)
+ _json["metadata"] = *_settings.metadata;
+}
+
+void json::to_json(Json& _json, StandardJSONInput const& _input)
+{
+ _json["language"] = "Solidity";
+
+ for (auto& [name, source] : _input.sources)
+ _json["sources"][name]["content"] = source;
+
+ if (_input.settings)
+ {
+ _json["settings"] = *_input.settings;
+ for (auto& [name, source] : _input.sources)
+ {
+ _json["settings"]["libraries"][name] = _input.libraries | ranges::views::transform([](auto const& entry) {
+ auto const& [libraryName, address] = entry;
+ auto parts = libraryName | ranges::views::split(':') | ranges::to>();
+ return std::pair{parts.back(), "0x" + address.hex()};
+ }) | ranges::to();
+ }
+ _json["settings"]["outputSelection"]["*"]["*"] = Json::array({"*"});
+ _json["settings"]["outputSelection"]["*"][""] = Json::array({"ast"});
+ }
+}
+
diff --git a/libsolidity/interface/StandardJSONInput.h b/libsolidity/interface/StandardJSONInput.h
new file mode 100644
index 000000000000..a4c339124697
--- /dev/null
+++ b/libsolidity/interface/StandardJSONInput.h
@@ -0,0 +1,158 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+using namespace solidity;
+using namespace solidity::util;
+
+namespace solidity::frontend::json
+{
+
+namespace input
+{
+ struct YulOptimizerDetails
+ {
+ /// Improve allocation of stack slots for variables, can free up stack slots early.
+ /// Default: true if Yul optimizer is enabled.
+ std::optional stackAllocation;
+ /// Optimization step sequence. The general form of the value is ":".
+ /// If it does not contain the ':' delimiter, it is interpreted as the main
+ /// sequence and the default is used for the cleanup sequence.
+ /// Default: true.
+ std::optional optimizerSteps;
+ };
+
+ struct OptimizerDetails
+ {
+ // Peephole optimizer (opcode-based). Default: true.
+ std::optional peephole = std::nullopt;
+ // Inliner (opcode-based). Optional. Default: true when optimization is enabled.
+ std::optional inliner = std::nullopt;
+ // Unused JUMPDEST remover (opcode-based). Default: true.
+ std::optional jumpdestRemover = std::nullopt;
+ // Literal reordering (codegen-based). Default: true when optimization is enabled.
+ std::optional orderLiterals = std::nullopt;
+ // Block deduplicator (opcode-based). Default: true when optimization is enabled.
+ std::optional deduplicate = std::nullopt;
+ // Common subexpression elimination (opcode-based). Default: true when optimization is enabled.
+ std::optional cse = std::nullopt;
+ // Constant optimizer (opcode-based). Default: true when optimization is enabled.
+ std::optional constantOptimizer = std::nullopt;
+ // Unchecked loop increment (codegen-based). Default: true.
+ std::optional simpleCounterForLoopUncheckedIncrement = std::nullopt;
+ // Yul optimizer. Default: true when optimization is enabled.
+ std::optional yul = std::nullopt;
+ /// Tuning options for the Yul optimizer.
+ std::optional yulDetails;
+ };
+
+ struct Optimizer
+ {
+ /// Turn on the optimizer. Default: false.
+ std::optional enable;
+ /// Optimize for how many times you intend to run the code. Default: 200.
+ std::optional runs;
+ /// State of all optimizer components.
+ std::optional details;
+ };
+
+ struct Debug
+ {
+ /// How to treat revert (and require) reason strings. Default: `RevertStrings::Default`.
+ std::optional revertStrings = std::nullopt;
+ };
+
+ struct Metadata
+ {
+ /// The CBOR metadata is appended at the end of the bytecode by default. Default: true.
+ /// Setting this to false omits the metadata from the runtime and deploy time code
+ std::optional appendCBOR = std::nullopt;
+ /// Use the given hash method for the metadata hash that is appended to the bytecode. Default: `MetadataHash::IPFS`.
+ std::optional bytecodeHash = std::nullopt;
+ };
+
+ struct Settings
+ {
+ /// Experimental mode toggle. Default: false.
+ std::optional experimental = std::nullopt;
+ /// The optimizer settings.
+ std::optional optimizer = std::nullopt;
+ /// Version of the EVM to compile for.
+ std::optional evmVersion = std::nullopt;
+ /// EVM Object Format version to compile for (experimental).
+ std::optional eofVersion = std::nullopt;
+ /// Change compilation pipeline to go through the Yul intermediate representation. Default: false.
+ std::optional viaIR = std::nullopt;
+ /// Turn on SSA CFG-based code generation via the IR (experimental, implies viaIR: true). Default: true;
+ std::optional viaSSACFG = std::nullopt;
+ /// Debugging settings.
+ std::optional debug = std::nullopt;
+ /// Metadata settings.
+ std::optional metadata = std::nullopt;
+ };
+
+ ///
+ void to_json(Json&, YulOptimizerDetails const&);
+ void to_json(Json&, OptimizerDetails const&);
+ void to_json(Json&, Optimizer const&);
+ void to_json(Json&, Debug const&);
+ void to_json(Json&, Metadata const&);
+ void to_json(Json&, Settings const&);
+}
+
+/**
+ * The input the compiler is requested to compile with. It carries source and
+ * compiler configuration.
+ */
+struct StandardJSONInput
+{
+ /// Source code which should be be compiled.
+ std::map sources = {};
+ /// Information on which library is deployed where.
+ std::map libraries = {};
+ /// Contract name without a colon prefix.
+ std::optional contractName = std::nullopt;
+ /// The compiler settings, e.g. EVM version, optimizer settings and Yul config.
+ std::optional settings = std::nullopt;
+};
+
+///
+void to_json(Json&, StandardJSONInput const&);
+
+}
diff --git a/libsolidity/interface/StandardJSONOutput.cpp b/libsolidity/interface/StandardJSONOutput.cpp
new file mode 100644
index 000000000000..5dab3cc6e9d5
--- /dev/null
+++ b/libsolidity/interface/StandardJSONOutput.cpp
@@ -0,0 +1,168 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+using namespace solidity::frontend;
+using namespace solidity::frontend::json;
+using namespace solidity::frontend::json::output;
+
+ABI const& Contract::abi() const
+{
+ if (!m_abi)
+ m_abi = m_raw.at("abi");
+ return *m_abi;
+}
+
+std::string const& Contract::metadata() const
+{
+ if (!m_metadata)
+ m_metadata = m_raw.at("metadata");
+ return *m_metadata;
+}
+
+EVM const& Contract::evm() const
+{
+ if (!m_evm)
+ m_evm = m_raw.at("evm");
+ return *m_evm;
+}
+
+void output::from_json(Json const& _json, SourceLocation& _sourceLocation)
+{
+ _sourceLocation = SourceLocation{
+ _json["file"],
+ _json["start"],
+ _json["end"],
+ _json.contains("message") ? std::optional{_json.at("message")} : std::nullopt
+ };
+}
+
+void output::from_json(Json const& _json, Error& _error)
+{
+ if (_json.contains("sourceLocation"))
+ _error.sourceLocation = _json.at("sourceLocation");
+ if (_json.contains("secondarySourceLocations") && _json.at("secondarySourceLocations").is_array())
+ _error.secondarySourceLocations = _json.at("secondarySourceLocations");
+ if (_json.contains("errorCode"))
+ _error.errorCode = langutil::ErrorId{std::stoull(_json.at("errorCode").get())};
+
+ auto type = langutil::Error::parseErrorType(_json.at("type"));
+ solAssert(type);
+
+ _error.type = type.value();
+ _error.message = _json.at("message");
+}
+
+void output::from_json(Json const& _json, Source& _source)
+{
+ _source.id = _json.at("id");
+ if (_json.contains("ast"))
+ _source.ast = _json.at("ast");
+}
+
+void output::from_json(Json const& _json, ABIParameter& _param)
+{
+ _param.name = _json.at("name").get();
+ _param.type = _json.at("type").get();
+ _param.internalType = _json.contains("internalType") ?
+ std::optional{_json.at("internalType")} :
+ std::nullopt;
+ _param.indexed = _json.contains("indexed") ?
+ std::optional{_json.at("indexed").get()} :
+ std::nullopt;
+ _param.components = _json.contains("components") ?
+ std::optional{_json.at("components").get>()} :
+ std::nullopt;
+}
+
+void output::from_json(Json const& _json, ABIConstructor& _constructor)
+{
+ _constructor.stateMutability = stateMutabilityFromString(_json.at("stateMutability"));
+ _constructor.inputs = _json.at("inputs").get>();
+}
+
+
+void output::from_json(Json const& _json, ABIFunction& _function)
+{
+ _function.name = _json.at("name");
+ _function.stateMutability = stateMutabilityFromString(_json.at("stateMutability"));;
+ _function.inputs = _json.at("inputs").get>();
+ _function.outputs = _json.at("outputs").get>();
+}
+
+void output::from_json(Json const& _json, ABIEvent& _event)
+{
+ _event.name = _json.at("name");
+ _event.isAnonymous = _json.at("anonymous");
+ _event.inputs = _json.at("inputs").get>();
+}
+
+void output::from_json(Json const& _json, ABIError& _event)
+{
+ _event.name = _json.at("name");
+ _event.inputs = _json.at("inputs").get>();
+}
+
+void output::from_json(Json const& _json, ABIEntry& _entry)
+{
+ auto const type = _json.at("type").get();
+ if (type == "constructor")
+ _entry = _json.get();
+ else if (type == "function")
+ _entry = _json.get();
+ else if (type == "event")
+ _entry = _json.get();
+ else if (type == "error")
+ _entry = _json.get();
+}
+
+void output::from_json(Json const& _json, ByteOffset& _byteOffset)
+{
+ _byteOffset.start = _json.at("start").get();
+ _byteOffset.length = _json.at("length").get();
+}
+
+void output::from_json(Json const& _json, Bytecode& _bytecode)
+{
+ _bytecode.object = util::fromHex(_json.at("object").get());
+ _bytecode.linkReferences = _json.at("linkReferences");
+}
+
+void output::from_json(Json const& _json, EVM& _evm)
+{
+ _evm.bytecode = _json.at("bytecode").get();
+ _evm.methodIdentifiers = _json.at("methodIdentifiers");
+}
+
+void output::from_json(Json const& _json, Contracts& _contracts)
+{
+ for (auto const& [source, contractsJson] : _json.items())
+ for (auto const& [name, contractJson] : contractsJson.items())
+ _contracts[source].push_back(output::Contract{name, contractJson});
+}
diff --git a/libsolidity/interface/StandardJSONOutput.h b/libsolidity/interface/StandardJSONOutput.h
new file mode 100644
index 000000000000..9884fdfc0c7e
--- /dev/null
+++ b/libsolidity/interface/StandardJSONOutput.h
@@ -0,0 +1,318 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#pragma once
+
+
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+using namespace solidity;
+using namespace solidity::util;
+
+namespace solidity::frontend::json
+{
+
+namespace output
+{
+ struct SourceLocation
+ {
+ /// The name of the source file.
+ std::string file;
+ /// The start of the source position.
+ int start;
+ /// The end of the source position.
+ int end;
+ /// If this is a secondary source location, a message should exist.
+ std::optional message;
+
+ /// @returns this source location converted to the compiler's internal type.
+ langutil::SourceLocation toInternalSourceLocation() const
+ {
+ return langutil::SourceLocation{start, end, std::make_shared(file)};
+ }
+ };
+
+ struct Error
+ {
+ /// Location within the source file.
+ std::optional sourceLocation;
+ /// Further locations (e.g. places of conflicting declarations).
+ std::optional> secondarySourceLocations;
+ /// Unique code for the cause of the error.
+ std::optional errorCode;
+ /// The error type.
+ langutil::Error::Type type;
+ /// The error message.
+ std::optional message;
+
+ /// @returns this error converted to the compiler's internal type.
+ langutil::Error toInternalError() const
+ {
+ auto locations = secondarySourceLocations.value_or(std::vector{});
+ return {
+ errorCode.value_or({}),
+ type,
+ message.value_or({}),
+ sourceLocation.value_or({}).toInternalSourceLocation(),
+ langutil::SecondarySourceLocation{
+ locations | ranges::views::filter([](auto const& s) {
+ return s.message.has_value();
+ }) | ranges::views::transform([](auto const& s) {
+ return std::pair{s.message.value(), s.toInternalSourceLocation()};
+ }) | ranges::to()
+ }
+ };
+ }
+ };
+
+ struct Source
+ {
+ /// Identifier of the source (used in source maps)
+ size_t id;
+ /// The AST object
+ std::optional ast;
+ };
+
+ struct ABIParameter
+ {
+ /// The ABI-level type name, e.g. "address", "uint256"
+ std::string name;
+ /// The ABI-level type, e.g. "address", "uint256", "tuple"
+ std::string type;
+ /// The Solidity-level type, may differ for e.g. enums or user-defined value types.
+ std::optional internalType;
+ /// Whether this parameter is indexed. Only present for event inputs.
+ std::optional indexed;
+ /// Component parameters, only present when type == "tuple"
+ std::optional> components;
+ };
+
+ struct ABIConstructor
+ {
+ /// The constrcutor's input parameters.
+ std::vector inputs;
+ /// The state mutability of the constructor: "pure", "view", "nonpayable", or "payable".
+ StateMutability stateMutability;
+ };
+
+ struct ABIFunction
+ {
+ /// The name of the function.
+ std::string name;
+ /// The function's input parameters.
+ std::vector inputs;
+ /// The function's output parameters.
+ std::vector outputs;
+ /// The state mutability of the function: "pure", "view", "nonpayable", or "payable".
+ StateMutability stateMutability;
+ };
+
+ struct ABIEvent
+ {
+ /// The name of the event.
+ std::string name;
+ /// The event's parameters.
+ std::vector inputs;
+ /// Whether the event is anonymous. Anonymous events do not have their
+ /// signature included in the topic list.
+ bool isAnonymous;
+ };
+
+ struct ABIError
+ {
+ /// The name of the error.
+ std::string name;
+ /// The error's parameters.
+ std::vector inputs;
+ };
+
+ struct ByteOffset
+ {
+ /// The start of the bytes to replace.
+ size_t start;
+ /// The length of the bytes to replace.
+ size_t length;
+ };
+
+ using LinkReferences = std::map>;
+
+ struct Bytecode
+ {
+ /// The bytecode as a hex.
+ bytes object;
+ /// The byte offsets per source and library. If not empty, this is an unlinked object.
+ std::map linkReferences;
+ };
+
+ struct EVM
+ {
+ /// The bytecode as a hex.
+ Bytecode bytecode;
+ /// The list of function hashes.
+ std::map methodIdentifiers;
+ };
+
+ /// A single entry in the contract ABI, either an event or a function.
+ using ABIEntry = std::variant;
+ using ABI = std::vector;
+
+ /**
+ * Represents a compiled contract. Carries the contract-specific compiler output.
+ */
+ class Contract
+ {
+ public:
+ /// Creates with a name and the raw JSON object representing this contract.
+ explicit Contract(std::string const& _name, Json _raw):
+ m_name(_name),
+ m_raw(_raw)
+ {}
+
+ /// @returns the contract name.
+ std::string const& name() const
+ {
+ return m_name;
+ }
+
+ /// @returns a reference to the raw JSON object representing this contract.
+ Json const& raw() const
+ {
+ return m_raw;
+ }
+
+ /// @returns the contract ABI definitions.
+ ABI const& abi() const;
+
+ /// @returns the metadata matching the pipeline selected using the viaIR setting.
+ std::string const& metadata() const;
+
+ /// @returns the EVM-related outputs
+ EVM const& evm() const;
+
+ protected:
+ std::string m_name;
+ Json m_raw;
+
+ private:
+ mutable std::optional m_abi;
+ mutable std::optional m_metadata;
+ mutable std::optional m_evm;
+ };
+
+ using Errors = std::vector;
+ using Sources = std::map;
+ using Contracts = std::map>;
+
+ /// Enables JSON deserialization for standard output types.
+ /// Supports parsing via `nlohmann::json`'s ADL pattern.
+ void from_json(Json const&, SourceLocation&);
+ void from_json(Json const&, Error&);
+ void from_json(Json const&, Source&);
+ void from_json(Json const&, ABIParameter&);
+ void from_json(Json const&, ABIConstructor&);
+ void from_json(Json const&, ABIFunction&);
+ void from_json(Json const&, ABIEvent&);
+ void from_json(Json const&, ABIError&);
+ void from_json(Json const&, ABIEntry&);
+ void from_json(Json const&, ByteOffset&);
+ void from_json(Json const&, Bytecode&);
+ void from_json(Json const&, EVM&);
+ void from_json(Json const&, Contracts&);
+}
+
+/**
+ * Output generated by the compiler during the last compilation run. It stores
+ * the raw JSON output and provides accessors that deserialize lazily.
+ */
+class StandardJSONOutput
+{
+public:
+ /// Creates a standard output object that takes ownership of the JSON output given.
+ StandardJSONOutput(Json _raw):
+ m_raw(std::move(_raw))
+ {}
+
+ /// Noncopyable, but has move semantics.
+ StandardJSONOutput(const StandardJSONOutput&) = delete;
+ StandardJSONOutput& operator=(const StandardJSONOutput&) = delete;
+ StandardJSONOutput(StandardJSONOutput&&) noexcept = default;
+ StandardJSONOutput& operator=(StandardJSONOutput&&) noexcept = default;
+
+ ~StandardJSONOutput() = default;
+
+ /// @retusn the raw JSON output produced by the compiler.
+ Json const& raw() const
+ {
+ return m_raw;
+ }
+
+ /// @returns all errors, warnings, infos that may have occurred during compilation.
+ output::Errors const& errors() const
+ {
+ if (!m_errors)
+ m_errors = m_raw.contains("errors") ? m_raw.at("errors") : output::Errors{};
+ return *m_errors;
+ }
+
+ /// @returns the file-level outputs. Can be limited / filtered by the `outputSelection` input.
+ output::Sources const& sources() const
+ {
+ if (!m_sources)
+ m_sources = m_raw.contains("sources") ? m_raw.at("sources") : output::Sources{};
+ return *m_sources;
+ }
+
+
+ /// @returns a map of all sources with their contracts.
+ output::Contracts const& contracts() const
+ {
+ if (!m_contracts)
+ m_contracts = m_raw.contains("contracts") ? m_raw.at("contracts") : output::Contracts{};
+ return *m_contracts;
+ }
+
+private:
+ Json m_raw;
+ mutable std::optional m_errors;
+ mutable std::optional m_sources;
+ mutable std::optional m_contracts;
+};
+
+}
diff --git a/test/libsolidity/interface/StandardJSON.cpp b/test/libsolidity/interface/StandardJSON.cpp
new file mode 100644
index 000000000000..95f1fc54c29d
--- /dev/null
+++ b/test/libsolidity/interface/StandardJSON.cpp
@@ -0,0 +1,58 @@
+/*
+ This file is part of solidity.
+
+ solidity is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ solidity is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with solidity. If not, see .
+*/
+// SPDX-License-Identifier: GPL-3.0
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+using namespace solidity::util;
+using namespace solidity::test;
+
+#define TEST_CASE_NAME (boost::unit_test::framework::current_test_case().p_name)
+
+namespace solidity::frontend::test
+{
+
+BOOST_AUTO_TEST_SUITE(StandardJSONTests)
+
+BOOST_AUTO_TEST_CASE(default_creation)
+{
+ json::StandardJSONInput input;
+
+ BOOST_CHECK_EQUAL(input.settings.has_value(), false);
+}
+
+BOOST_AUTO_TEST_CASE(default_to_json)
+{
+ using namespace solidity::frontend::json;
+
+ Json json{StandardJSONInput{}};
+
+ BOOST_CHECK_EQUAL(json["language"], "Solidity");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace solidity::frontend::test
+