Allow returning metadata in StandardCompiler without compilation

This commit is contained in:
Alex Beregszaszi 2019-02-28 13:08:21 +00:00 committed by chriseth
parent 26ca144647
commit fcbb8ec51c
3 changed files with 64 additions and 2 deletions

View File

@ -10,6 +10,7 @@ Compiler Features:
* Inline Assembly: Consider ``extcodehash`` as part of Constantinople.
* Inline Assembly: Instructions unavailable to the currently configured EVM are errors now.
* SMTChecker: Do not report underflow/overflow if they always revert. This removes false positives when using ``SafeMath``.
* Standard JSON Interface: Allow retrieving metadata without triggering compilation.
* Static Analyzer: Warn about expressions with custom types when they have no effect.
* Optimizer: Add rule for shifts with constants for Constantinople.
* Optimizer: Combine multiple shifts with constant shift-by values into one.

View File

@ -201,7 +201,6 @@ bool isBinaryRequested(Json::Value const& _outputSelection)
// This does not inculde "evm.methodIdentifiers" on purpose!
static vector<string> const outputsThatRequireBinaries{
"*",
"metadata", // This is only generated at the end of compilation, but could be generated earlier.
"evm.deployedBytecode", "evm.deployedBytecode.object", "evm.deployedBytecode.opcodes",
"evm.deployedBytecode.sourceMap", "evm.deployedBytecode.linkReferences",
"evm.bytecode", "evm.bytecode.object", "evm.bytecode.opcodes", "evm.bytecode.sourceMap",
@ -777,7 +776,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
Json::Value contractData(Json::objectValue);
if (isArtifactRequested(outputSelection, file, name, "abi"))
contractData["abi"] = m_compilerStack.contractABI(contractName);
if (compilationSuccess && isArtifactRequested(outputSelection, file, name, "metadata"))
if (isArtifactRequested(outputSelection, file, name, "metadata"))
contractData["metadata"] = m_compilerStack.metadata(contractName);
if (isArtifactRequested(outputSelection, file, name, "userdoc"))
contractData["userdoc"] = m_compilerStack.natspecUser(contractName);

View File

@ -1015,6 +1015,68 @@ BOOST_AUTO_TEST_CASE(optimizer_settings_details_different)
BOOST_CHECK(optimizer["runs"].asUInt() == 600);
}
BOOST_AUTO_TEST_CASE(metadata_without_compilation)
{
// NOTE: the contract code here should fail to compile due to "out of stack"
// If the metadata is successfully returned, that means no compilation was attempted.
char const* input = R"(
{
"language": "Solidity",
"settings": {
"outputSelection": {
"fileA": { "A": [ "metadata" ] }
}
},
"sources": {
"fileA": {
"content": "contract A {
function x(uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h, uint i, uint j, uint k, uint l, uint m, uint n, uint o, uint p) pure public {}
function y() pure public {
uint a; uint b; uint c; uint d; uint e; uint f; uint g; uint h; uint i; uint j; uint k; uint l; uint m; uint n; uint o; uint p;
x(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p);
}
}"
}
}
}
)";
Json::Value result = compile(input);
BOOST_CHECK(containsAtMostWarnings(result));
Json::Value contract = getContractResult(result, "fileA", "A");
BOOST_CHECK(contract.isObject());
BOOST_CHECK(contract["metadata"].isString());
BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString()));
}
BOOST_AUTO_TEST_CASE(common_pattern)
{
char const* input = R"(
{
"language": "Solidity",
"settings": {
"outputSelection": {
"*": {
"*": [ "evm.bytecode.object", "metadata" ]
}
}
},
"sources": {
"fileA": {
"content": "contract A { function f() pure public {} }"
}
}
}
)";
Json::Value result = compile(input);
BOOST_CHECK(containsAtMostWarnings(result));
Json::Value contract = getContractResult(result, "fileA", "A");
BOOST_CHECK(contract.isObject());
BOOST_CHECK(contract["metadata"].isString());
BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString()));
BOOST_CHECK(contract["evm"]["bytecode"].isObject());
BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString());
}
BOOST_AUTO_TEST_SUITE_END()
}