Update EVMHost to match EVMC10 changes

This commit is contained in:
Alex Beregszaszi 2022-09-16 12:56:23 +02:00
parent 458857d0d6
commit 5df92a374b
9 changed files with 94 additions and 104 deletions

View File

@ -125,7 +125,7 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
else else
assertThrow(false, Exception, "Unsupported EVM version"); assertThrow(false, Exception, "Unsupported EVM version");
tx_context.block_difficulty = evmc::uint256be{200000000}; tx_context.block_prev_randao = evmc::uint256be{200000000}; // TODO: should make it >2**64 for >Paris
tx_context.block_gas_limit = 20000000; tx_context.block_gas_limit = 20000000;
tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address; tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address;
tx_context.tx_gas_price = evmc::uint256be{3000000000}; tx_context.tx_gas_price = evmc::uint256be{3000000000};
@ -145,7 +145,6 @@ EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
void EVMHost::reset() void EVMHost::reset()
{ {
accounts.clear(); accounts.clear();
m_currentAddress = {};
// Clear self destruct records // Clear self destruct records
recorded_selfdestructs.clear(); recorded_selfdestructs.clear();
// Clear call records // Clear call records
@ -194,14 +193,14 @@ void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recip
_recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value); _recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value);
} }
void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept bool EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept
{ {
// TODO actual selfdestruct is even more complicated. // TODO actual selfdestruct is even more complicated.
transfer(accounts[_addr], accounts[_beneficiary], convertFromEVMC(accounts[_addr].balance)); transfer(accounts[_addr], accounts[_beneficiary], convertFromEVMC(accounts[_addr].balance));
// Record self destructs. Clearing will be done in newTransactionFrame(). // Record self destructs. Clearing will be done in newTransactionFrame().
MockedHost::selfdestruct(_addr, _beneficiary); return MockedHost::selfdestruct(_addr, _beneficiary);
} }
void EVMHost::recordCalls(evmc_message const& _message) noexcept void EVMHost::recordCalls(evmc_message const& _message) noexcept
@ -212,34 +211,34 @@ void EVMHost::recordCalls(evmc_message const& _message) noexcept
// NOTE: this is used for both internal and external calls. // NOTE: this is used for both internal and external calls.
// External calls are triggered from ExecutionFramework and contain only EVMC_CREATE or EVMC_CALL. // External calls are triggered from ExecutionFramework and contain only EVMC_CREATE or EVMC_CALL.
evmc::result EVMHost::call(evmc_message const& _message) noexcept evmc::Result EVMHost::call(evmc_message const& _message) noexcept
{ {
recordCalls(_message); recordCalls(_message);
if (_message.destination == 0x0000000000000000000000000000000000000001_address) if (_message.recipient == 0x0000000000000000000000000000000000000001_address)
return precompileECRecover(_message); return precompileECRecover(_message);
else if (_message.destination == 0x0000000000000000000000000000000000000002_address) else if (_message.recipient == 0x0000000000000000000000000000000000000002_address)
return precompileSha256(_message); return precompileSha256(_message);
else if (_message.destination == 0x0000000000000000000000000000000000000003_address) else if (_message.recipient == 0x0000000000000000000000000000000000000003_address)
return precompileRipeMD160(_message); return precompileRipeMD160(_message);
else if (_message.destination == 0x0000000000000000000000000000000000000004_address) else if (_message.recipient == 0x0000000000000000000000000000000000000004_address)
return precompileIdentity(_message); return precompileIdentity(_message);
else if (_message.destination == 0x0000000000000000000000000000000000000005_address && m_evmVersion >= langutil::EVMVersion::byzantium()) else if (_message.recipient == 0x0000000000000000000000000000000000000005_address && m_evmVersion >= langutil::EVMVersion::byzantium())
return precompileModExp(_message); return precompileModExp(_message);
else if (_message.destination == 0x0000000000000000000000000000000000000006_address && m_evmVersion >= langutil::EVMVersion::byzantium()) else if (_message.recipient == 0x0000000000000000000000000000000000000006_address && m_evmVersion >= langutil::EVMVersion::byzantium())
{ {
if (m_evmVersion <= langutil::EVMVersion::istanbul()) if (m_evmVersion <= langutil::EVMVersion::istanbul())
return precompileALTBN128G1Add<EVMC_ISTANBUL>(_message); return precompileALTBN128G1Add<EVMC_ISTANBUL>(_message);
else else
return precompileALTBN128G1Add<EVMC_LONDON>(_message); return precompileALTBN128G1Add<EVMC_LONDON>(_message);
} }
else if (_message.destination == 0x0000000000000000000000000000000000000007_address && m_evmVersion >= langutil::EVMVersion::byzantium()) else if (_message.recipient == 0x0000000000000000000000000000000000000007_address && m_evmVersion >= langutil::EVMVersion::byzantium())
{ {
if (m_evmVersion <= langutil::EVMVersion::istanbul()) if (m_evmVersion <= langutil::EVMVersion::istanbul())
return precompileALTBN128G1Mul<EVMC_ISTANBUL>(_message); return precompileALTBN128G1Mul<EVMC_ISTANBUL>(_message);
else else
return precompileALTBN128G1Mul<EVMC_LONDON>(_message); return precompileALTBN128G1Mul<EVMC_LONDON>(_message);
} }
else if (_message.destination == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium()) else if (_message.recipient == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium())
{ {
if (m_evmVersion <= langutil::EVMVersion::istanbul()) if (m_evmVersion <= langutil::EVMVersion::istanbul())
return precompileALTBN128PairingProduct<EVMC_ISTANBUL>(_message); return precompileALTBN128PairingProduct<EVMC_ISTANBUL>(_message);
@ -262,7 +261,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
message.gas -= message.input_data[i] == 0 ? evmasm::GasCosts::txDataZeroGas : evmasm::GasCosts::txDataNonZeroGas(m_evmVersion); message.gas -= message.input_data[i] == 0 ? evmasm::GasCosts::txDataZeroGas : evmasm::GasCosts::txDataNonZeroGas(m_evmVersion);
if (message.gas < 0) if (message.gas < 0)
{ {
evmc::result result({}); evmc::Result result;
result.status_code = EVMC_OUT_OF_GAS; result.status_code = EVMC_OUT_OF_GAS;
accounts = stateBackup; accounts = stateBackup;
return result; return result;
@ -299,8 +298,8 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
encodedNonce encodedNonce
), h160::AlignRight); ), h160::AlignRight);
message.destination = convertToEVMC(createAddress); message.recipient = convertToEVMC(createAddress);
assertThrow(accounts.count(message.destination) == 0, Exception, "Account cannot exist"); assertThrow(accounts.count(message.recipient) == 0, Exception, "Account cannot exist");
code = evmc::bytes(message.input_data, message.input_data + message.input_size); code = evmc::bytes(message.input_data, message.input_data + message.input_size);
} }
@ -313,13 +312,13 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes()
), h160::AlignRight); ), h160::AlignRight);
message.destination = convertToEVMC(createAddress); message.recipient = convertToEVMC(createAddress);
if (accounts.count(message.destination) && ( if (accounts.count(message.recipient) && (
accounts[message.destination].nonce > 0 || accounts[message.recipient].nonce > 0 ||
!accounts[message.destination].code.empty() !accounts[message.recipient].code.empty()
)) ))
{ {
evmc::result result({}); evmc::Result result;
result.status_code = EVMC_OUT_OF_GAS; result.status_code = EVMC_OUT_OF_GAS;
accounts = stateBackup; accounts = stateBackup;
return result; return result;
@ -327,21 +326,16 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
code = evmc::bytes(message.input_data, message.input_data + message.input_size); code = evmc::bytes(message.input_data, message.input_data + message.input_size);
} }
else if (message.kind == EVMC_DELEGATECALL || message.kind == EVMC_CALLCODE)
{
code = accounts[message.destination].code;
message.destination = m_currentAddress;
}
else else
code = accounts[message.destination].code; code = accounts[message.code_address].code;
auto& destination = accounts[message.destination]; auto& destination = accounts[message.recipient];
if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE) if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE)
{ {
if (value > convertFromEVMC(sender.balance)) if (value > convertFromEVMC(sender.balance))
{ {
evmc::result result({}); evmc::Result result;
result.status_code = EVMC_INSUFFICIENT_BALANCE; result.status_code = EVMC_INSUFFICIENT_BALANCE;
accounts = stateBackup; accounts = stateBackup;
return result; return result;
@ -355,12 +349,9 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
if (m_evmRevision >= EVMC_BERLIN) if (m_evmRevision >= EVMC_BERLIN)
{ {
access_account(message.sender); access_account(message.sender);
access_account(message.destination); access_account(message.recipient);
} }
evmc::address currentAddress = m_currentAddress; evmc::Result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size());
m_currentAddress = message.destination;
evmc::result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size());
m_currentAddress = currentAddress;
if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2) if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2)
{ {
@ -373,7 +364,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
} }
else else
{ {
result.create_address = message.destination; result.create_address = message.recipient;
destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size); destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size);
destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size})); destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size}));
} }
@ -416,7 +407,7 @@ evmc::bytes32 EVMHost::convertToEVMC(h256 const& _data)
return d; return d;
} }
evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept
{ {
// NOTE this is a partial implementation for some inputs. // NOTE this is a partial implementation for some inputs.
@ -449,20 +440,14 @@ evmc::result EVMHost::precompileECRecover(evmc_message const& _message) noexcept
} }
} }
}; };
evmc::result result = precompileGeneric(_message, inputOutput); evmc::Result result = precompileGeneric(_message, inputOutput);
// ECRecover will return success with empty response in case of failure // ECRecover will return success with empty response in case of failure
if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS) if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS)
// return resultWithGas(_message.gas, gas_cost, {}); return resultWithGas(_message.gas, gas_cost, {});
{
result.status_code = EVMC_SUCCESS;
result.gas_left = _message.gas - gas_cost;
result.output_data = {};
result.output_size = 0;
}
return result; return result;
} }
evmc::result EVMHost::precompileSha256(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileSha256(evmc_message const& _message) noexcept
{ {
// static data so that we do not need a release routine... // static data so that we do not need a release routine...
bytes static hash; bytes static hash;
@ -477,7 +462,7 @@ evmc::result EVMHost::precompileSha256(evmc_message const& _message) noexcept
return resultWithGas(_message.gas, gas_cost, hash); return resultWithGas(_message.gas, gas_cost, hash);
} }
evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept
{ {
// NOTE this is a partial implementation for some inputs. // NOTE this is a partial implementation for some inputs.
@ -579,7 +564,7 @@ evmc::result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept
return precompileGeneric(_message, inputOutput); return precompileGeneric(_message, inputOutput);
} }
evmc::result EVMHost::precompileIdentity(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileIdentity(evmc_message const& _message) noexcept
{ {
// static data so that we do not need a release routine... // static data so that we do not need a release routine...
bytes static data; bytes static data;
@ -591,14 +576,14 @@ evmc::result EVMHost::precompileIdentity(evmc_message const& _message) noexcept
return resultWithGas(_message.gas, gas_cost, data); return resultWithGas(_message.gas, gas_cost, data);
} }
evmc::result EVMHost::precompileModExp(evmc_message const&) noexcept evmc::Result EVMHost::precompileModExp(evmc_message const&) noexcept
{ {
// TODO implement // TODO implement
return resultWithFailure(); return resultWithFailure();
} }
template <evmc_revision Revision> template <evmc_revision Revision>
evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noexcept
{ {
// NOTE this is a partial implementation for some inputs. // NOTE this is a partial implementation for some inputs.
@ -866,7 +851,7 @@ evmc::result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noex
} }
template <evmc_revision Revision> template <evmc_revision Revision>
evmc::result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noexcept
{ {
// NOTE this is a partial implementation for some inputs. // NOTE this is a partial implementation for some inputs.
@ -956,7 +941,7 @@ evmc::result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noex
} }
template <evmc_revision Revision> template <evmc_revision Revision>
evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _message) noexcept evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _message) noexcept
{ {
// Base + per pairing gas. // Base + per pairing gas.
constexpr auto calc_cost = [](unsigned points) -> int64_t { constexpr auto calc_cost = [](unsigned points) -> int64_t {
@ -1124,7 +1109,7 @@ evmc::result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _mess
return precompileGeneric(_message, inputOutput); return precompileGeneric(_message, inputOutput);
} }
evmc::result EVMHost::precompileGeneric( evmc::Result EVMHost::precompileGeneric(
evmc_message const& _message, evmc_message const& _message,
map<bytes, EVMPrecompileOutput> const& _inOut) noexcept map<bytes, EVMPrecompileOutput> const& _inOut) noexcept
{ {
@ -1138,20 +1123,20 @@ evmc::result EVMHost::precompileGeneric(
return resultWithFailure(); return resultWithFailure();
} }
evmc::result EVMHost::resultWithFailure() noexcept evmc::Result EVMHost::resultWithFailure() noexcept
{ {
evmc::result result({}); evmc::Result result;
result.status_code = EVMC_FAILURE; result.status_code = EVMC_FAILURE;
return result; return result;
} }
evmc::result EVMHost::resultWithGas( evmc::Result EVMHost::resultWithGas(
int64_t gas_limit, int64_t gas_limit,
int64_t gas_required, int64_t gas_required,
bytes const& _data bytes const& _data
) noexcept ) noexcept
{ {
evmc::result result({}); evmc::Result result;
if (gas_limit < gas_required) if (gas_limit < gas_required)
{ {
result.status_code = EVMC_OUT_OF_GAS; result.status_code = EVMC_OUT_OF_GAS;
@ -1162,7 +1147,7 @@ evmc::result EVMHost::resultWithGas(
result.status_code = EVMC_SUCCESS; result.status_code = EVMC_SUCCESS;
result.gas_left = gas_limit - gas_required; result.gas_left = gas_limit - gas_required;
} }
result.output_data = _data.data(); result.output_data = _data.empty() ? nullptr : _data.data();
result.output_size = _data.size(); result.output_size = _data.size();
return result; return result;
} }
@ -1209,9 +1194,10 @@ void EVMHostPrinter::balance()
void EVMHostPrinter::selfdestructRecords() void EVMHostPrinter::selfdestructRecords()
{ {
for (auto const& record: m_host.recorded_selfdestructs) for (auto const& record: m_host.recorded_selfdestructs)
for (auto const& beneficiary: record.second)
m_stateStream << "SELFDESTRUCT" m_stateStream << "SELFDESTRUCT"
<< " BENEFICIARY " << " BENEFICIARY "
<< m_host.convertFromEVMC(record.beneficiary) << m_host.convertFromEVMC(beneficiary)
<< endl; << endl;
} }

View File

@ -35,7 +35,7 @@
namespace solidity::test namespace solidity::test
{ {
using Address = util::h160; using Address = util::h160;
using StorageMap = std::map<evmc::bytes32, evmc::storage_value>; using StorageMap = std::map<evmc::bytes32, evmc::StorageValue>;
struct EVMPrecompileOutput { struct EVMPrecompileOutput {
bytes const output; bytes const output;
@ -59,8 +59,8 @@ public:
using MockedHost::access_storage; using MockedHost::access_storage;
// Modified features of MockedHost. // Modified features of MockedHost.
void selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept final; bool selfdestruct(evmc::address const& _addr, evmc::address const& _beneficiary) noexcept final;
evmc::result call(evmc_message const& _message) noexcept final; evmc::Result call(evmc_message const& _message) noexcept final;
evmc::bytes32 get_block_hash(int64_t number) const noexcept final; evmc::bytes32 get_block_hash(int64_t number) const noexcept final;
// Solidity testing specific features. // Solidity testing specific features.
@ -98,35 +98,34 @@ public:
static util::h256 convertFromEVMC(evmc::bytes32 const& _data); static util::h256 convertFromEVMC(evmc::bytes32 const& _data);
static evmc::bytes32 convertToEVMC(util::h256 const& _data); static evmc::bytes32 convertToEVMC(util::h256 const& _data);
private: private:
evmc::address m_currentAddress = {};
/// Transfer value between accounts. Checks for sufficient balance. /// Transfer value between accounts. Checks for sufficient balance.
void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept; void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept;
/// Start a new transaction frame. /// Start a new transaction frame.
/// This will perform selfdestructs and clear account/storage access indicator for EIP-2929. /// This will perform selfdestructs, apply storage status changes across all accounts,
/// and clear account/storage access indicator for EIP-2929.
void newTransactionFrame(); void newTransactionFrame();
/// Records calls made via @param _message. /// Records calls made via @param _message.
void recordCalls(evmc_message const& _message) noexcept; void recordCalls(evmc_message const& _message) noexcept;
static evmc::result precompileECRecover(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 precompileSha256(evmc_message const& _message) noexcept;
static evmc::result precompileRipeMD160(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 precompileIdentity(evmc_message const& _message) noexcept;
static evmc::result precompileModExp(evmc_message const& _message) noexcept; static evmc::Result precompileModExp(evmc_message const& _message) noexcept;
template <evmc_revision Revision> template <evmc_revision Revision>
static evmc::result precompileALTBN128G1Add(evmc_message const& _message) noexcept; static evmc::Result precompileALTBN128G1Add(evmc_message const& _message) noexcept;
template <evmc_revision Revision> template <evmc_revision Revision>
static evmc::result precompileALTBN128G1Mul(evmc_message const& _message) noexcept; static evmc::Result precompileALTBN128G1Mul(evmc_message const& _message) noexcept;
template <evmc_revision Revision> template <evmc_revision Revision>
static evmc::result precompileALTBN128PairingProduct(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, EVMPrecompileOutput> const& _inOut) noexcept; static evmc::Result precompileGeneric(evmc_message const& _message, std::map<bytes, EVMPrecompileOutput> const& _inOut) noexcept;
/// @returns a result object with gas usage and result data taken from @a _data. /// @returns a result object with gas usage and result data taken from @a _data.
/// The outcome will be a failure if the limit < required. /// The outcome will be a failure if the limit < required.
/// @note The return value is only valid as long as @a _data is alive! /// @note The return value is only valid as long as @a _data is alive!
static evmc::result resultWithGas(int64_t gas_limit, int64_t gas_required, bytes const& _data) noexcept; static evmc::Result resultWithGas(int64_t gas_limit, int64_t gas_required, bytes const& _data) noexcept;
static evmc::result resultWithFailure() noexcept; static evmc::Result resultWithFailure() noexcept;
evmc::VM& m_vm; evmc::VM& m_vm;
/// EVM version requested by the testing tool /// EVM version requested by the testing tool

View File

@ -165,7 +165,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
cout << " value: " << _value << endl; cout << " value: " << _value << endl;
cout << " in: " << util::toHex(_data) << endl; cout << " in: " << util::toHex(_data) << endl;
} }
evmc_message message = {}; evmc_message message{};
message.input_data = _data.data(); message.input_data = _data.data();
message.input_size = _data.size(); message.input_size = _data.size();
message.sender = EVMHost::convertToEVMC(m_sender); message.sender = EVMHost::convertToEVMC(m_sender);
@ -174,16 +174,19 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
if (_isCreation) if (_isCreation)
{ {
message.kind = EVMC_CREATE; message.kind = EVMC_CREATE;
message.destination = EVMHost::convertToEVMC(h160{}); message.recipient = {};
message.code_address = {};
} }
else else
{ {
message.kind = EVMC_CALL; message.kind = EVMC_CALL;
message.destination = EVMHost::convertToEVMC(m_contractAddress); message.recipient = EVMHost::convertToEVMC(m_contractAddress);
message.code_address = message.recipient;
} }
message.gas = InitialGas.convert_to<int64_t>(); message.gas = InitialGas.convert_to<int64_t>();
evmc::result result = m_evmcHost->call(message); evmc::Result result = m_evmcHost->call(message);
m_output = bytes(result.output_data, result.output_data + result.output_size); m_output = bytes(result.output_data, result.output_data + result.output_size);
if (_isCreation) if (_isCreation)
@ -210,11 +213,12 @@ void ExecutionFramework::sendEther(h160 const& _addr, u256 const& _amount)
if (_amount > 0) if (_amount > 0)
cout << " value: " << _amount << endl; cout << " value: " << _amount << endl;
} }
evmc_message message = {}; evmc_message message{};
message.sender = EVMHost::convertToEVMC(m_sender); message.sender = EVMHost::convertToEVMC(m_sender);
message.value = EVMHost::convertToEVMC(_amount); message.value = EVMHost::convertToEVMC(_amount);
message.kind = EVMC_CALL; message.kind = EVMC_CALL;
message.destination = EVMHost::convertToEVMC(_addr); message.recipient = EVMHost::convertToEVMC(_addr);
message.code_address = message.recipient;
message.gas = InitialGas.convert_to<int64_t>(); message.gas = InitialGas.convert_to<int64_t>();
m_evmcHost->call(message); m_evmcHost->call(message);

View File

@ -272,7 +272,6 @@ private:
} }
protected: protected:
u256 const GasPrice = 10 * gwei;
u256 const InitialGas = 100000000; u256 const InitialGas = 100000000;
void selectVM(evmc_capabilities _cap = evmc_capabilities::EVMC_CAPABILITY_EVM1); void selectVM(evmc_capabilities _cap = evmc_capabilities::EVMC_CAPABILITY_EVM1);

View File

@ -83,31 +83,32 @@ evmc_message EvmoneUtility::initializeMessage(bytes const& _input)
return msg; return msg;
} }
evmc::result EvmoneUtility::executeContract( evmc::Result EvmoneUtility::executeContract(
bytes const& _functionHash, bytes const& _functionHash,
evmc_address _deployedAddress evmc_address _deployedAddress
) )
{ {
evmc_message message = initializeMessage(_functionHash); evmc_message message = initializeMessage(_functionHash);
message.destination = _deployedAddress; message.recipient = _deployedAddress;
message.code_address = _deployedAddress;
message.kind = EVMC_CALL; message.kind = EVMC_CALL;
return m_evmHost.call(message); return m_evmHost.call(message);
} }
evmc::result EvmoneUtility::deployContract(bytes const& _code) evmc::Result EvmoneUtility::deployContract(bytes const& _code)
{ {
evmc_message message = initializeMessage(_code); evmc_message message = initializeMessage(_code);
message.kind = EVMC_CREATE; message.kind = EVMC_CREATE;
return m_evmHost.call(message); return m_evmHost.call(message);
} }
evmc::result EvmoneUtility::deployAndExecute( evmc::Result EvmoneUtility::deployAndExecute(
bytes const& _byteCode, bytes const& _byteCode,
string const& _hexEncodedInput string const& _hexEncodedInput
) )
{ {
// Deploy contract and signal failure if deploy failed // Deploy contract and signal failure if deploy failed
evmc::result createResult = deployContract(_byteCode); evmc::Result createResult = deployContract(_byteCode);
solAssert( solAssert(
createResult.status_code == EVMC_SUCCESS, createResult.status_code == EVMC_SUCCESS,
"SolidityEvmoneInterface: Contract creation failed" "SolidityEvmoneInterface: Contract creation failed"
@ -115,7 +116,7 @@ evmc::result EvmoneUtility::deployAndExecute(
// Execute test function and signal failure if EVM reverted or // Execute test function and signal failure if EVM reverted or
// did not return expected output on successful execution. // did not return expected output on successful execution.
evmc::result callResult = executeContract( evmc::Result callResult = executeContract(
util::fromHex(_hexEncodedInput), util::fromHex(_hexEncodedInput),
createResult.create_address createResult.create_address
); );
@ -128,7 +129,7 @@ evmc::result EvmoneUtility::deployAndExecute(
return callResult; return callResult;
} }
evmc::result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle) evmc::Result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle)
{ {
map<string, h160> libraryAddressMap; map<string, h160> libraryAddressMap;
// Stage 1: Compile and deploy library if present. // Stage 1: Compile and deploy library if present.
@ -139,7 +140,7 @@ evmc::result EvmoneUtility::compileDeployAndExecute(string _fuzzIsabelle)
solAssert(compilationOutput.has_value(), "Compiling library failed"); solAssert(compilationOutput.has_value(), "Compiling library failed");
CompilerOutput cOutput = compilationOutput.value(); CompilerOutput cOutput = compilationOutput.value();
// Deploy contract and signal failure if deploy failed // Deploy contract and signal failure if deploy failed
evmc::result createResult = deployContract(cOutput.byteCode); evmc::Result createResult = deployContract(cOutput.byteCode);
solAssert( solAssert(
createResult.status_code == EVMC_SUCCESS, createResult.status_code == EVMC_SUCCESS,
"SolidityEvmoneInterface: Library deployment failed" "SolidityEvmoneInterface: Library deployment failed"

View File

@ -122,7 +122,7 @@ public:
/// and executing test configuration. /// and executing test configuration.
/// @param _isabelleData contains encoding data to be passed to the /// @param _isabelleData contains encoding data to be passed to the
/// isabelle test entry point. /// isabelle test entry point.
evmc::result compileDeployAndExecute(std::string _isabelleData = {}); evmc::Result compileDeployAndExecute(std::string _isabelleData = {});
/// Compares the contents of the memory address pointed to /// Compares the contents of the memory address pointed to
/// by `_result` of `_length` bytes to u256 zero. /// by `_result` of `_length` bytes to u256 zero.
/// @returns true if `_result` is zero, false /// @returns true if `_result` is zero, false
@ -138,17 +138,17 @@ private:
/// @returns the result of the execution of the function whose /// @returns the result of the execution of the function whose
/// keccak256 hash is @param _functionHash that is deployed at /// keccak256 hash is @param _functionHash that is deployed at
/// @param _deployedAddress in @param _hostContext. /// @param _deployedAddress in @param _hostContext.
evmc::result executeContract( evmc::Result executeContract(
bytes const& _functionHash, bytes const& _functionHash,
evmc_address _deployedAddress evmc_address _deployedAddress
); );
/// @returns the result of deployment of @param _code on @param _hostContext. /// @returns the result of deployment of @param _code on @param _hostContext.
evmc::result deployContract(bytes const& _code); evmc::Result deployContract(bytes const& _code);
/// Deploys and executes EVM byte code in @param _byteCode on /// Deploys and executes EVM byte code in @param _byteCode on
/// EVM Host referenced by @param _hostContext. Input passed /// EVM Host referenced by @param _hostContext. Input passed
/// to execution context is @param _hexEncodedInput. /// to execution context is @param _hexEncodedInput.
/// @returns result returning by @param _hostContext. /// @returns result returning by @param _hostContext.
evmc::result deployAndExecute( evmc::Result deployAndExecute(
bytes const& _byteCode, bytes const& _byteCode,
std::string const& _hexEncodedInput std::string const& _hexEncodedInput
); );

View File

@ -87,11 +87,11 @@ DEFINE_PROTO_FUZZER(Program const& _input)
return; return;
} }
evmc::result deployResult = YulEvmoneUtility{}.deployCode(unoptimisedByteCode, hostContext); evmc::Result deployResult = YulEvmoneUtility{}.deployCode(unoptimisedByteCode, hostContext);
if (deployResult.status_code != EVMC_SUCCESS) if (deployResult.status_code != EVMC_SUCCESS)
return; return;
auto callMessage = YulEvmoneUtility{}.callMessage(deployResult.create_address); auto callMessage = YulEvmoneUtility{}.callMessage(deployResult.create_address);
evmc::result callResult = hostContext.call(callMessage); evmc::Result callResult = hostContext.call(callMessage);
// If the fuzzer synthesized input does not contain the revert opcode which // If the fuzzer synthesized input does not contain the revert opcode which
// we lazily check by string find, the EVM call should not revert. // we lazily check by string find, the EVM call should not revert.
bool noRevertInSource = yul_source.find("revert") == string::npos; bool noRevertInSource = yul_source.find("revert") == string::npos;
@ -132,13 +132,13 @@ DEFINE_PROTO_FUZZER(Program const& _input)
// Reset host before running optimised code. // Reset host before running optimised code.
hostContext.reset(); hostContext.reset();
evmc::result deployResultOpt = YulEvmoneUtility{}.deployCode(optimisedByteCode, hostContext); evmc::Result deployResultOpt = YulEvmoneUtility{}.deployCode(optimisedByteCode, hostContext);
solAssert( solAssert(
deployResultOpt.status_code == EVMC_SUCCESS, deployResultOpt.status_code == EVMC_SUCCESS,
"Evmone: Optimized contract creation failed" "Evmone: Optimized contract creation failed"
); );
auto callMessageOpt = YulEvmoneUtility{}.callMessage(deployResultOpt.create_address); auto callMessageOpt = YulEvmoneUtility{}.callMessage(deployResultOpt.create_address);
evmc::result callResultOpt = hostContext.call(callMessageOpt); evmc::Result callResultOpt = hostContext.call(callMessageOpt);
if (noRevertInSource) if (noRevertInSource)
solAssert( solAssert(
callResultOpt.status_code != EVMC_REVERT, callResultOpt.status_code != EVMC_REVERT,

View File

@ -38,7 +38,7 @@ bytes YulAssembler::assemble()
return m_stack.assemble(YulStack::Machine::EVM).bytecode->bytecode; return m_stack.assemble(YulStack::Machine::EVM).bytecode->bytecode;
} }
evmc::result YulEvmoneUtility::deployCode(bytes const& _input, EVMHost& _host) evmc::Result YulEvmoneUtility::deployCode(bytes const& _input, EVMHost& _host)
{ {
// Zero initialize all message fields // Zero initialize all message fields
evmc_message msg = {}; evmc_message msg = {};
@ -74,7 +74,8 @@ evmc_message YulEvmoneUtility::callMessage(evmc_address _address)
{ {
evmc_message call = {}; evmc_message call = {};
call.gas = std::numeric_limits<int64_t>::max(); call.gas = std::numeric_limits<int64_t>::max();
call.destination = _address; call.recipient = _address;
call.code_address = _address;
call.kind = EVMC_CALL; call.kind = EVMC_CALL;
return call; return call;
} }

View File

@ -54,7 +54,7 @@ private:
struct YulEvmoneUtility struct YulEvmoneUtility
{ {
/// @returns the result of deploying bytecode @param _input on @param _host. /// @returns the result of deploying bytecode @param _input on @param _host.
static evmc::result deployCode(solidity::bytes const& _input, EVMHost& _host); static evmc::Result deployCode(solidity::bytes const& _input, EVMHost& _host);
/// @returns call message to be sent to @param _address. /// @returns call message to be sent to @param _address.
static evmc_message callMessage(evmc_address _address); static evmc_message callMessage(evmc_address _address);
/// @returns true if call result indicates a serious error, false otherwise. /// @returns true if call result indicates a serious error, false otherwise.