Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ set(libsolidity_util_sources
libsolidity/util/ContractABIUtils.h
libsolidity/util/SoltestErrors.h
libsolidity/util/SoltestTypes.h
libsolidity/util/TestFileParser.cpp
libsolidity/util/StandardJSONCompiler.cpp
libsolidity/util/StandardJSONCompiler.h
libsolidity/util/TestFileParser.cpp
libsolidity/util/TestFileParser.h
libsolidity/util/TestFileParserTests.cpp
libsolidity/util/TestFunctionCall.cpp
Expand Down
2 changes: 1 addition & 1 deletion test/ExecutionFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class ExecutionFramework
std::string const& _contractName = "",
bytes const& _arguments = {},
std::map<std::string, util::h160> const& _libraryAddresses = {},
std::optional<std::string> const& _sourceName = std::nullopt
std::optional<std::string> const& _mainSourceName = std::nullopt
) = 0;

bytes const& compileAndRun(
Expand Down
20 changes: 16 additions & 4 deletions test/libsolidity/GasCosts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
* Tests that check that the cost of certain operations stay within range.
*/

#include <test/libsolidity/util/SoltestErrors.h>
#include <test/libsolidity/SolidityExecutionFramework.h>

#include <liblangutil/EVMVersion.h>
#include <libsolutil/IpfsHash.h>
#include <libevmasm/GasMeter.h>
Expand All @@ -38,7 +40,10 @@ namespace solidity::frontend::test
#define CHECK_DEPLOY_GAS(_gasNoOpt, _gasOpt, _evmVersion) \
do \
{ \
u256 metaCost = GasMeter::dataGas(m_compiler.cborMetadata(m_compiler.lastContractName()), true, _evmVersion); \
auto const& output = m_compiler.output(); \
auto const* contract = output.contract(); \
soltestAssert(contract); \
u256 metaCost = GasMeter::dataGas(bytes{}, true, _evmVersion); \
u256 gasOpt{_gasOpt}; \
u256 gasNoOpt{_gasNoOpt}; \
u256 gas = m_optimiserSettings == OptimiserSettings::minimal() ? gasNoOpt : gasOpt; \
Expand Down Expand Up @@ -90,7 +95,7 @@ BOOST_AUTO_TEST_CASE(string_storage)
}
}
)";
m_compiler.setMetadataFormat(CompilerStack::MetadataFormat::NoMetadata);

m_appendCBORMetadata = false;
compileAndRun(sourceCode);

Expand Down Expand Up @@ -202,8 +207,15 @@ BOOST_AUTO_TEST_CASE(single_callvaluecheck)
}
)";
compileAndRun(sourceCode);
size_t bytecodeSizeNonpayable = m_compiler.object("Nonpayable").bytecode.size();
size_t bytecodeSizePayable = m_compiler.object("Payable").bytecode.size();
auto const& output = m_compiler.output();
auto const* nonpayable = output.contract("Nonpayable");
auto const* payable = output.contract("Payable");

soltestAssert(nonpayable);
soltestAssert(payable);

size_t bytecodeSizeNonpayable = nonpayable->evm().bytecode.object.size();
size_t bytecodeSizePayable = payable->evm().bytecode.object.size();

auto evmVersion = solidity::test::CommonOptions::get().evmVersion();
if (evmVersion < EVMVersion::shanghai())
Expand Down
51 changes: 39 additions & 12 deletions test/libsolidity/GasMeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,16 @@
* Unit tests for the gas estimator.
*/

#include "libsolidity/interface/StandardJSONInput.h"
#include <test/libsolidity/SolidityExecutionFramework.h>

#include <test/libsolidity/util/Common.h>
#include <test/libsolidity/util/SoltestErrors.h>

#include <libevmasm/GasMeter.h>
#include <libevmasm/KnownState.h>
#include <libevmasm/PathGasMeter.h>

#include <libsolidity/ast/AST.h>
#include <libsolidity/interface/GasEstimator.h>

Expand All @@ -42,25 +48,42 @@ class GasMeterTestFramework: public SolidityExecutionFramework
public:
void compile(std::string const& _sourceCode)
{
m_compiler.reset();
m_compiler.setSources({{"", "pragma solidity >=0.0;\n"
"// SPDX-License-Identifier: GPL-3.0\n" + _sourceCode}});
m_compiler.setOptimiserSettings(solidity::test::CommonOptions::get().optimize);
m_compiler.setEVMVersion(m_evmVersion);
BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed");
m_compilerInput = json::StandardJSONInput{
.sources = {{"", withPreamble(_sourceCode)}},
.settings = json::input::Settings{
.optimizer = json::input::Optimizer{
.enable = CommonOptions::get().optimize,
.runs = 200,
.details = json::input::OptimizerDetails{}
},
.evmVersion = m_evmVersion,
}
};
m_compiler.compile(m_compilerInput);

BOOST_REQUIRE_MESSAGE(m_compiler.output().success(), "Compiling contract failed");
}

void testCreationTimeGas(std::string const& _sourceCode, u256 const& _tolerance = u256(0))
{
compileAndRun(_sourceCode);

auto state = std::make_shared<KnownState>();
PathGasMeter meter(*m_compiler.assemblyItems(m_compiler.lastContractName()), solidity::test::CommonOptions::get().evmVersion());
auto const* contract = m_compiler.output().contract();

soltestAssert(contract);

PathGasMeter meter(
{}, // TODO(erikli): Fix!
CommonOptions::get().evmVersion()
);
GasMeter::GasConsumption gas = meter.estimateMax(0, state);
u256 bytecodeSize(m_compiler.runtimeObject(m_compiler.lastContractName()).bytecode.size());
bytes const& object = contract->evm().bytecode.object;
u256 bytecodeSize(object.size());
// costs for deployment
gas += bytecodeSize * GasCosts::createDataGas;
// costs for transaction
gas += gasForTransaction(m_compiler.object(m_compiler.lastContractName()).bytecode, true);
gas += gasForTransaction(object, true);

BOOST_REQUIRE(!gas.isInfinite);
BOOST_CHECK_LE(m_gasUsed, gas.value);
Expand All @@ -71,6 +94,10 @@ class GasMeterTestFramework: public SolidityExecutionFramework
/// against the actual gas usage computed by the VM on the given set of argument variants.
void testRunTimeGas(std::string const& _sig, std::vector<bytes> _argumentVariants, u256 const& _tolerance = u256(0))
{
auto const* contract = m_compiler.output().contract();

soltestAssert(contract);

u256 gasUsed = 0;
GasMeter::GasConsumption gas;
util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig);
Expand All @@ -82,8 +109,8 @@ class GasMeterTestFramework: public SolidityExecutionFramework
gas = std::max(gas, gasForTransaction(hash.asBytes() + arguments, false));
}

gas += GasEstimator(solidity::test::CommonOptions::get().evmVersion()).functionalEstimation(
*m_compiler.runtimeAssemblyItems(m_compiler.lastContractName()),
gas += GasEstimator(CommonOptions::get().evmVersion()).functionalEstimation(
{}, // TODO(erikli): Fix!
_sig
);
BOOST_REQUIRE(!gas.isInfinite);
Expand All @@ -93,7 +120,7 @@ class GasMeterTestFramework: public SolidityExecutionFramework

static GasMeter::GasConsumption gasForTransaction(bytes const& _data, bool _isCreation)
{
auto evmVersion = solidity::test::CommonOptions::get().evmVersion();
auto evmVersion = CommonOptions::get().evmVersion();
GasMeter::GasConsumption gas = _isCreation ? GasCosts::txCreateGas : GasCosts::txGas;
for (auto i: _data)
gas += i != 0 ? GasCosts::txDataNonZeroGas(evmVersion) : GasCosts::txDataZeroGas;
Expand Down
Loading