mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
EVMHost: Add tracing features needed for fuzzing.
This commit is contained in:
+75
-12
@@ -142,6 +142,8 @@ void EVMHost::reset()
|
||||
m_currentAddress = {};
|
||||
// Clear self destruct records
|
||||
recorded_selfdestructs.clear();
|
||||
// Clear call records
|
||||
recorded_calls.clear();
|
||||
|
||||
// Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161).
|
||||
// NOTE: keep this in sync with `EVMHost::call` below.
|
||||
@@ -167,11 +169,21 @@ void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _ben
|
||||
accounts.erase(_addr);
|
||||
accounts[_beneficiary].balance = balance;
|
||||
// Record self destructs
|
||||
recorded_selfdestructs.push_back({_addr, _beneficiary});
|
||||
recorded_selfdestructs.push_back({_addr, _beneficiary, balance});
|
||||
}
|
||||
|
||||
void EVMHost::recordCalls(evmc_message const& _message) noexcept
|
||||
{
|
||||
if (recorded_calls.empty())
|
||||
recorded_calls.reserve(max_recorded_calls);
|
||||
|
||||
if (recorded_calls.size() < max_recorded_calls)
|
||||
recorded_calls.emplace_back(_message);
|
||||
}
|
||||
|
||||
evmc::result EVMHost::call(evmc_message const& _message) noexcept
|
||||
{
|
||||
recordCalls(_message);
|
||||
if (_message.destination == 0x0000000000000000000000000000000000000001_address)
|
||||
return precompileECRecover(_message);
|
||||
else if (_message.destination == 0x0000000000000000000000000000000000000002_address)
|
||||
@@ -761,17 +773,6 @@ evmc::result EVMHost::resultWithGas(
|
||||
return result;
|
||||
}
|
||||
|
||||
void EVMHost::print_all_storage(ostringstream& _os)
|
||||
{
|
||||
for (auto const& [addr, mockedAccount]: accounts)
|
||||
{
|
||||
_os << "Address: " << convertFromEVMC(addr) << endl;
|
||||
for (auto const& [slot, value]: get_address_storage(addr))
|
||||
if (get_storage(addr, slot))
|
||||
_os << convertFromEVMC(slot) << ": " << convertFromEVMC(value.value) << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void EVMHost::print_storage_at(evmc::address const& _addr, ostringstream& _os)
|
||||
{
|
||||
for (auto const& [slot, value]: get_address_storage(_addr))
|
||||
@@ -784,3 +785,65 @@ StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr)
|
||||
assertThrow(account_exists(_addr), Exception, "Account does not exist.");
|
||||
return accounts[_addr].storage;
|
||||
}
|
||||
|
||||
void EVMHost::print_call_records(std::ostringstream& _os) const noexcept
|
||||
{
|
||||
auto callKind = [](evmc_call_kind _kind) -> string
|
||||
{
|
||||
switch (_kind)
|
||||
{
|
||||
case evmc_call_kind::EVMC_CALL:
|
||||
return "CALL";
|
||||
case evmc_call_kind::EVMC_DELEGATECALL:
|
||||
return "DELEGATECALL";
|
||||
case evmc_call_kind::EVMC_CALLCODE:
|
||||
return "CALLCODE";
|
||||
case evmc_call_kind::EVMC_CREATE:
|
||||
return "CREATE";
|
||||
case evmc_call_kind::EVMC_CREATE2:
|
||||
return "CREATE2";
|
||||
default:
|
||||
assertThrow(false, Exception, "Invalid call kind.");
|
||||
}
|
||||
};
|
||||
|
||||
for (auto const& record: recorded_calls)
|
||||
_os << callKind(record.kind)
|
||||
<< " VALUE "
|
||||
<< convertFromEVMC(record.value)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void EVMHost::print_selfdestruct_records(ostringstream& _os) const noexcept
|
||||
{
|
||||
for (auto const& record: recorded_selfdestructs)
|
||||
_os << "SELFDESTRUCT"
|
||||
<< " BENEFICIARY "
|
||||
<< convertFromEVMC(record.beneficiary)
|
||||
<< " BALANCE "
|
||||
<< convertFromEVMC(record.balance)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
void EVMHost::print_balance(evmc::address const& _addr, ostringstream& _os) const noexcept
|
||||
{
|
||||
_os << "BALANCE " << convertFromEVMC(get_balance(_addr)) << endl;
|
||||
}
|
||||
|
||||
string EVMHost::dumpState(evmc::address _addr)
|
||||
{
|
||||
ostringstream stateStream;
|
||||
|
||||
// Print state and execution trace.
|
||||
if (account_exists(_addr))
|
||||
{
|
||||
print_storage_at(_addr, stateStream);
|
||||
print_balance(_addr, stateStream);
|
||||
}
|
||||
else
|
||||
print_selfdestruct_records(stateStream);
|
||||
|
||||
print_call_records(stateStream);
|
||||
|
||||
return stateStream.str();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user