/*
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
namespace solidity::test::fuzzer
{
struct CompilerOutput
{
/// EVM bytecode returned by compiler
solidity::bytes byteCode;
/// Method identifiers in a contract
Json::Value methodIdentifiersInContract;
};
struct CompilerInput
{
CompilerInput(
langutil::EVMVersion _evmVersion,
StringMap const& _sourceCode,
std::string const& _contractName,
frontend::OptimiserSettings _optimiserSettings,
std::map _libraryAddresses,
bool _debugFailure = false,
bool _viaIR = false
):
evmVersion(_evmVersion),
sourceCode(_sourceCode),
contractName(_contractName),
optimiserSettings(_optimiserSettings),
libraryAddresses(_libraryAddresses),
debugFailure(_debugFailure),
viaIR(_viaIR)
{}
/// EVM target version
langutil::EVMVersion evmVersion;
/// Source code to be compiled
StringMap const& sourceCode;
/// Contract name without a colon prefix
std::string contractName;
/// Optimiser setting to be used during compilation
frontend::OptimiserSettings optimiserSettings;
/// Information on which library is deployed where
std::map libraryAddresses;
/// Flag used for debugging
bool debugFailure;
/// Flag to enable new code generator.
bool viaIR;
};
class SolidityCompilationFramework
{
public:
SolidityCompilationFramework(CompilerInput _input): m_compilerInput(_input)
{}
/// Sets contract name to @param _contractName.
void contractName(std::string const& _contractName)
{
m_compilerInput.contractName = _contractName;
}
/// Sets library addresses to @param _libraryAddresses.
void libraryAddresses(std::map _libraryAddresses)
{
m_compilerInput.libraryAddresses = std::move(_libraryAddresses);
}
/// @returns method identifiers in contract called @param _contractName.
Json::Value methodIdentifiers(std::string const& _contractName)
{
return m_compiler.interfaceSymbols(_contractName)["methods"];
}
/// @returns Compilation output comprising EVM bytecode and list of
/// method identifiers in contract if compilation is successful,
/// null value otherwise.
std::optional compileContract();
private:
frontend::CompilerStack m_compiler;
CompilerInput m_compilerInput;
};
class EvmoneUtility
{
public:
EvmoneUtility(
solidity::test::EVMHost& _evmHost,
CompilerInput _compilerInput,
std::string const& _contractName,
std::string const& _libraryName,
std::string const& _methodName
):
m_evmHost(_evmHost),
m_compilationFramework(_compilerInput),
m_contractName(_contractName),
m_libraryName(_libraryName),
m_methodName(_methodName)
{}
/// @returns the result returned by the EVM host on compiling, deploying,
/// and executing test configuration.
/// @param _isabelleData contains encoding data to be passed to the
/// isabelle test entry point.
std::optional compileDeployAndExecute(std::string _isabelleData = {});
/// Compares the contents of the memory address pointed to
/// by `_result` of `_length` bytes to u256 zero.
/// @returns true if `_result` is zero, false
/// otherwise.
static bool zeroWord(uint8_t const* _result, size_t _length);
/// @returns an evmc_message with all of its fields zero
/// initialized except gas and input fields.
/// The gas field is set to the maximum permissible value so that we
/// don't run into out of gas errors. The input field is copied from
/// @param _input.
static evmc_message initializeMessage(bytes const& _input);
private:
/// @returns the result of the execution of the function whose
/// keccak256 hash is @param _functionHash that is deployed at
/// @param _deployedAddress in @param _hostContext.
evmc::result executeContract(
bytes const& _functionHash,
evmc_address _deployedAddress
);
/// @returns the result of deployment of @param _code on @param _hostContext.
evmc::result deployContract(bytes const& _code);
/// Deploys and executes EVM byte code in @param _byteCode on
/// EVM Host referenced by @param _hostContext. Input passed
/// to execution context is @param _hexEncodedInput.
/// @returns result returning by @param _hostContext.
evmc::result deployAndExecute(
bytes const& _byteCode,
std::string const& _hexEncodedInput
);
/// Compiles contract named @param _contractName present in
/// @param _sourceCode, optionally using a precompiled library
/// specified via a library mapping and an optimisation setting.
/// @returns a pair containing the generated byte code and method
/// identifiers for methods in @param _contractName.
std::optional compileContract();
/// EVM Host implementation
solidity::test::EVMHost& m_evmHost;
/// Solidity compilation framework
SolidityCompilationFramework m_compilationFramework;
/// Contract name
std::string m_contractName;
/// Library name
std::string m_libraryName;
/// Method name
std::string m_methodName;
};
}