10#include <unordered_map>
60 std::unordered_map<bytes32, StorageValue>
storage;
69 for (std::size_t i = 0; i <
sizeof(x); ++i)
98 std::unordered_map<address, MockedAccount>
accounts;
135 std::vector<bytes> m_recorded_calls_inputs;
139 void record_account_access(
const address& addr)
const
152 record_account_access(addr);
159 record_account_access(addr);
161 const auto account_iter =
accounts.find(addr);
165 const auto storage_iter = account_iter->second.storage.find(key);
166 if (storage_iter != account_iter->second.storage.end())
167 return storage_iter->second.current;
174 const bytes32& value)
noexcept override
176 record_account_access(addr);
182 auto& s =
accounts[addr].storage[key];
192 const auto status = [&original = s.original, ¤t = s.current, &value]() {
198 if (current == value)
208 if (original == current)
244 RemoveClearsSchedule = 1 << 0,
245 AddClearsSchedule = 1 << 1,
246 RestoredBySet = 1 << 2,
247 RestoredByReset = 1 << 3,
249 int triggered_clauses = None;
260 triggered_clauses |= RemoveClearsSchedule;
268 triggered_clauses |= AddClearsSchedule;
274 if (original == value)
280 triggered_clauses |= RestoredBySet;
286 triggered_clauses |= RestoredByReset;
290 switch (triggered_clauses)
292 case RemoveClearsSchedule:
294 case AddClearsSchedule:
296 case RemoveClearsSchedule | RestoredByReset:
300 case RestoredByReset:
319 record_account_access(addr);
320 const auto it =
accounts.find(addr);
324 return it->second.balance;
330 record_account_access(addr);
331 const auto it =
accounts.find(addr);
334 return it->second.code.size();
340 record_account_access(addr);
341 const auto it =
accounts.find(addr);
344 return it->second.codehash;
350 uint8_t* buffer_data,
351 size_t buffer_size)
const noexcept override
353 record_account_access(addr);
354 const auto it =
accounts.find(addr);
358 const auto& code = it->second.code;
360 if (code_offset >= code.size())
363 const auto n = std::min(buffer_size, code.size() - code_offset);
366 std::copy_n(&code[code_offset], n, buffer_data);
373 record_account_access(addr);
375 beneficiaries.emplace_back(beneficiary);
376 return beneficiaries.size() == 1;
382 record_account_access(msg.recipient);
394 if (call_msg.input_size > 0)
396 m_recorded_calls_inputs.emplace_back(call_msg.input_data, call_msg.input_size);
397 const auto& input_copy = m_recorded_calls_inputs.back();
398 call_msg.input_data = input_copy.data();
419 size_t topics_count)
noexcept override
421 recorded_logs.push_back({addr, {data, data_size}, {topics, topics + topics_count}});
443 const auto already_accessed =
447 record_account_access(addr);
450 if (addr >= 0x0000000000000000000000000000000000000001_address &&
451 addr <= 0x0000000000000000000000000000000000000009_address)
473 auto& value =
accounts[addr].storage[key];
474 const auto access_status = value.access_status;
476 return access_status;
486 record_account_access(addr);
488 const auto account_iter =
accounts.find(addr);
492 const auto storage_iter = account_iter->second.transient_storage.find(key);
493 if (storage_iter != account_iter->second.transient_storage.end())
494 return storage_iter->second;
505 const bytes32& value)
noexcept override
507 record_account_access(addr);
508 accounts[addr].transient_storage[key] = value;
Abstract class to be used by Host implementations.
Mocked EVMC Host implementation.
size_t get_code_size(const address &addr) const noexcept override
Get the account's code size (EVMC host method).
size_t copy_code(const address &addr, size_t code_offset, uint8_t *buffer_data, size_t buffer_size) const noexcept override
Copy the account's code to the given buffer (EVMC host method).
uint256be get_balance(const address &addr) const noexcept override
Get the account's balance (EVMC Host method).
void emit_log(const address &addr, const uint8_t *data, size_t data_size, const bytes32 topics[], size_t topics_count) noexcept override
Emit LOG (EVMC host method).
evmc_tx_context get_tx_context() const noexcept override
Get transaction context (EVMC host method).
evmc_result call_result
The call result to be returned by the call() method.
bytes32 block_hash
The block header hash value to be returned by get_block_hash().
evmc_access_status access_account(const address &addr) noexcept override
Record an account access.
bool account_exists(const address &addr) const noexcept override
Returns true if an account exists (EVMC Host method).
static constexpr auto max_recorded_account_accesses
The maximum number of entries in recorded_account_accesses record.
std::unordered_map< address, MockedAccount > accounts
The set of all accounts in the Host, organized by their addresses.
Result call(const evmc_message &msg) noexcept override
Call/create other contract (EVMC host method).
bytes32 get_storage(const address &addr, const bytes32 &key) const noexcept override
Get the account's storage value at the given key (EVMC Host method).
std::vector< log_record > recorded_logs
The record of all LOGs passed to the emit_log() method.
evmc_access_status access_storage(const address &addr, const bytes32 &key) noexcept override
Access the account's storage value at the given key.
bytes32 get_code_hash(const address &addr) const noexcept override
Get the account's code hash (EVMC host method).
static constexpr auto max_recorded_calls
The maximum number of entries in recorded_calls record.
bytes32 get_transient_storage(const address &addr, const bytes32 &key) const noexcept override
Get account's transient storage.
evmc_storage_status set_storage(const address &addr, const bytes32 &key, const bytes32 &value) noexcept override
Set the account's storage value (EVMC Host method).
bool selfdestruct(const address &addr, const address &beneficiary) noexcept override
Selfdestruct the account (EVMC host method).
std::unordered_map< address, std::vector< address > > recorded_selfdestructs
The record of all SELFDESTRUCTs from the selfdestruct() method as a map selfdestructed_address => [be...
std::vector< int64_t > recorded_blockhashes
The record of all block numbers for which get_block_hash() was called.
bytes32 get_block_hash(int64_t block_number) const noexcept override
Get the block header hash (EVMC host method).
evmc_tx_context tx_context
The EVMC transaction context to be returned by get_tx_context().
void set_transient_storage(const address &addr, const bytes32 &key, const bytes32 &value) noexcept override
Set account's transient storage.
std::vector< address > recorded_account_accesses
The record of all account accesses.
std::vector< evmc_message > recorded_calls
The record of all call messages requested in the call() method.
The EVM code execution result.
evmc_access_status
Access status per EIP-2929: Gas cost increases for state access opcodes.
evmc_storage_status
The effect of an attempt to modify a contract storage item.
@ EVMC_ACCESS_COLD
The entry hasn't been accessed before – it's the first access.
@ EVMC_ACCESS_WARM
The entry is already in accessed_addresses or accessed_storage_keys.
@ EVMC_STORAGE_ADDED_DELETED
A storage item is deleted by changing the current dirty nonzero to the original zero value.
@ EVMC_STORAGE_MODIFIED_RESTORED
A storage item is modified by changing the current dirty nonzero to the original nonzero value other ...
@ EVMC_STORAGE_DELETED_RESTORED
A storage item is added by changing the current dirty zero to the original value.
@ EVMC_STORAGE_ADDED
A new storage item is added by changing the current clean zero to a nonzero value.
@ EVMC_STORAGE_MODIFIED_DELETED
A storage item is deleted by changing the current dirty nonzero to the zero value and the original va...
@ EVMC_STORAGE_ASSIGNED
The new/same value is assigned to the storage item without affecting the cost structure.
@ EVMC_STORAGE_DELETED
A storage item is deleted by changing the current clean nonzero to the zero value.
@ EVMC_STORAGE_DELETED_ADDED
A storage item is added by changing the current dirty zero to a nonzero value other than the original...
@ EVMC_STORAGE_MODIFIED
A storage item is modified by changing the current clean nonzero to other nonzero value.
EVMC C++ API - wrappers and bindings for C++.
constexpr bool is_zero(const address &a) noexcept
Checks if the given address is the zero address.
std::basic_string< unsigned char, byte_traits< unsigned char > > bytes
String of unsigned chars representing bytes.
bytes32 codehash
The code hash. Can be a value not related to the actual code.
std::unordered_map< bytes32, StorageValue > storage
The account storage map.
int nonce
The account nonce.
bytes code
The account code.
uint256be balance
The account balance.
std::unordered_map< bytes32, bytes32 > transient_storage
The account transient storage.
void set_balance(uint64_t x) noexcept
Helper method for setting balance by numeric type.
address creator
The address of the account which created the log.
bool operator==(const log_record &other) const noexcept
Equal operator.
std::vector< bytes32 > topics
The log topics.
bytes data
The data attached to the log.
Extended value (with original value and access flag) for account storage.
bytes32 original
The original storage value.
evmc_access_status access_status
Is the storage key cold or warm.
StorageValue() noexcept=default
Default constructor.
StorageValue(const bytes32 &_value, const bytes32 &_original, evmc_access_status _access_status=EVMC_ACCESS_COLD) noexcept
Constructor with original value and optional access status.
bytes32 current
The current storage value.
The big-endian 160-bit hash suitable for keeping an Ethereum address.
The fixed size array of 32 bytes for storing 256-bit EVM values.
uint8_t bytes[32]
The 32 bytes.
The message describing an EVM call, including a zero-depth calls from a transaction origin.
The EVM code execution result.
The transaction and block data for execution.