#pragma once
#include <test/evmc/mocked_host.hpp>
#include <test/evmc/evmc.hpp>
#include <test/evmc/evmc.h>
#include <liblangutil/EVMVersion.h>
#include <libsolutil/FixedHash.h>
#include <boost/filesystem.hpp>
namespace solidity::test
{
using Address = util::h160;
class EVMHost: public evmc::MockedHost
{
public:
using MockedHost::get_code_size;
using MockedHost::get_balance;
static evmc::VM& getVM(std::string const& _path = {});
static std::tuple<bool, bool> checkVmPaths(std::vector<boost::filesystem::path> const& _vmPaths);
explicit EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm);
void reset();
void resetWarmAccess();
void newBlock()
{
tx_context.block_number++;
tx_context.block_timestamp += 15;
recorded_logs.clear();
resetWarmAccess();
}
std::map<evmc::bytes32, evmc::storage_value> const& get_address_storage(evmc::address const& _addr);
bool account_exists(evmc::address const& _addr) const noexcept final
{
return evmc::MockedHost::account_exists(_addr);
}
void selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept final;
evmc::result call(evmc_message const& _message) noexcept final;
evmc::bytes32 get_block_hash(int64_t number) const noexcept final;
static Address convertFromEVMC(evmc::address const& _addr);
static evmc::address convertToEVMC(Address const& _addr);
static util::h256 convertFromEVMC(evmc::bytes32 const& _data);
static evmc::bytes32 convertToEVMC(util::h256 const& _data);
bool hasCapability(evmc_capabilities capability) const noexcept
{
return m_vm.has_capability(capability);
}
private:
evmc::address m_currentAddress = {};
void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept;
void recordCalls(evmc_message const& _message) noexcept;
static evmc::result precompileECRecover(evmc_message const& _message) noexcept;
static evmc::result precompileSha256(evmc_message const& _message) noexcept;
static evmc::result precompileRipeMD160(evmc_message const& _message) noexcept;
static evmc::result precompileIdentity(evmc_message const& _message) noexcept;
static evmc::result precompileModExp(evmc_message const& _message) noexcept;
static evmc::result precompileALTBN128G1Add(evmc_message const& _message) noexcept;
static evmc::result precompileALTBN128G1Mul(evmc_message const& _message) noexcept;
static evmc::result precompileALTBN128PairingProduct(evmc_message const& _message) noexcept;
static evmc::result precompileGeneric(evmc_message const& _message, std::map<bytes, bytes> const& _inOut) noexcept;
static evmc::result resultWithGas(evmc_message const& _message, bytes const& _data) noexcept;
evmc::VM& m_vm;
langutil::EVMVersion m_evmVersion;
evmc_revision m_evmRevision;
};
class EVMHostPrinter
{
public:
explicit EVMHostPrinter(EVMHost& _host, evmc::address _address):
m_host(_host),
m_account(_address)
{}
std::string state();
private:
void storage();
void callRecords();
void balance();
void selfdestructRecords();
std::ostringstream m_stateStream;
EVMHost& m_host;
evmc::address m_account;
};
}