Coverage Report

Created: 2026-10-26 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/test/evmc/evmc.hpp
Line
Count
Source
1
// EVMC: Ethereum Client-VM Connector API.
2
// Copyright 2018 The EVMC Authors.
3
// Licensed under the Apache License, Version 2.0.
4
#pragma once
5
6
#include <evmc/evmc.h>
7
#include <evmc/helpers.h>
8
#include <evmc/hex.hpp>
9
10
#include <functional>
11
#include <initializer_list>
12
#include <ostream>
13
#include <string_view>
14
#include <utility>
15
16
static_assert(EVMC_LATEST_STABLE_REVISION <= EVMC_MAX_REVISION,
17
              "latest stable revision ill-defined");
18
19
/// EVMC C++ API - wrappers and bindings for C++
20
/// @ingroup cpp
21
namespace evmc
22
{
23
/// The big-endian 160-bit hash suitable for keeping an Ethereum address.
24
///
25
/// This type wraps C ::evmc_address to make sure objects of this type are always initialized.
26
struct address : evmc_address
27
{
28
    /// Default and converting constructor.
29
    ///
30
    /// Initializes bytes to zeros if not other @p init value provided.
31
5.14M
    constexpr address(evmc_address init = {}) noexcept : evmc_address{init} {}
32
33
    /// Converting constructor from unsigned integer value.
34
    ///
35
    /// This constructor assigns the @p v value to the last 8 bytes [12:19]
36
    /// in big-endian order.
37
    constexpr explicit address(uint64_t v) noexcept
38
274k
      : evmc_address{{0,
39
274k
                      0,
40
274k
                      0,
41
274k
                      0,
42
274k
                      0,
43
274k
                      0,
44
274k
                      0,
45
274k
                      0,
46
274k
                      0,
47
274k
                      0,
48
274k
                      0,
49
274k
                      0,
50
274k
                      static_cast<uint8_t>(v >> 56),
51
274k
                      static_cast<uint8_t>(v >> 48),
52
274k
                      static_cast<uint8_t>(v >> 40),
53
274k
                      static_cast<uint8_t>(v >> 32),
54
274k
                      static_cast<uint8_t>(v >> 24),
55
274k
                      static_cast<uint8_t>(v >> 16),
56
274k
                      static_cast<uint8_t>(v >> 8),
57
274k
                      static_cast<uint8_t>(v >> 0)}}
58
274k
    {}
59
60
    /// Explicit operator converting to bool.
61
    inline constexpr explicit operator bool() const noexcept;
62
63
    /// Implicit operator converting to bytes_view.
64
0
    inline constexpr operator bytes_view() const noexcept { return {bytes, sizeof(bytes)}; }
65
};
66
67
/// The fixed size array of 32 bytes for storing 256-bit EVM values.
68
///
69
/// This type wraps C ::evmc_bytes32 to make sure objects of this type are always initialized.
70
struct bytes32 : evmc_bytes32
71
{
72
    /// Default and converting constructor.
73
    ///
74
    /// Initializes bytes to zeros if not other @p init value provided.
75
3.59M
    constexpr bytes32(evmc_bytes32 init = {}) noexcept : evmc_bytes32{init} {}
76
77
    /// Converting constructor from unsigned integer value.
78
    ///
79
    /// This constructor assigns the @p v value to the last 8 bytes [24:31]
80
    /// in big-endian order.
81
    constexpr explicit bytes32(uint64_t v) noexcept
82
323k
      : evmc_bytes32{{0,
83
323k
                      0,
84
323k
                      0,
85
323k
                      0,
86
323k
                      0,
87
323k
                      0,
88
323k
                      0,
89
323k
                      0,
90
323k
                      0,
91
323k
                      0,
92
323k
                      0,
93
323k
                      0,
94
323k
                      0,
95
323k
                      0,
96
323k
                      0,
97
323k
                      0,
98
323k
                      0,
99
323k
                      0,
100
323k
                      0,
101
323k
                      0,
102
323k
                      0,
103
323k
                      0,
104
323k
                      0,
105
323k
                      0,
106
323k
                      static_cast<uint8_t>(v >> 56),
107
323k
                      static_cast<uint8_t>(v >> 48),
108
323k
                      static_cast<uint8_t>(v >> 40),
109
323k
                      static_cast<uint8_t>(v >> 32),
110
323k
                      static_cast<uint8_t>(v >> 24),
111
323k
                      static_cast<uint8_t>(v >> 16),
112
323k
                      static_cast<uint8_t>(v >> 8),
113
323k
                      static_cast<uint8_t>(v >> 0)}}
114
323k
    {}
115
116
    /// Explicit operator converting to bool.
117
    inline constexpr explicit operator bool() const noexcept;
118
119
    /// Implicit operator converting to bytes_view.
120
0
    inline constexpr operator bytes_view() const noexcept { return {bytes, sizeof(bytes)}; }
121
};
122
123
/// The alias for evmc::bytes32 to represent a big-endian 256-bit integer.
124
using uint256be = bytes32;
125
126
127
/// Loads 64 bits / 8 bytes of data from the given @p data array in big-endian order.
128
inline constexpr uint64_t load64be(const uint8_t* data) noexcept
129
98.0M
{
130
98.0M
    return (uint64_t{data[0]} << 56) | (uint64_t{data[1]} << 48) | (uint64_t{data[2]} << 40) |
131
98.0M
           (uint64_t{data[3]} << 32) | (uint64_t{data[4]} << 24) | (uint64_t{data[5]} << 16) |
132
98.0M
           (uint64_t{data[6]} << 8) | uint64_t{data[7]};
133
98.0M
}
134
135
/// Loads 64 bits / 8 bytes of data from the given @p data array in little-endian order.
136
inline constexpr uint64_t load64le(const uint8_t* data) noexcept
137
34.3M
{
138
34.3M
    return uint64_t{data[0]} | (uint64_t{data[1]} << 8) | (uint64_t{data[2]} << 16) |
139
34.3M
           (uint64_t{data[3]} << 24) | (uint64_t{data[4]} << 32) | (uint64_t{data[5]} << 40) |
140
34.3M
           (uint64_t{data[6]} << 48) | (uint64_t{data[7]} << 56);
141
34.3M
}
142
143
/// Loads 32 bits / 4 bytes of data from the given @p data array in big-endian order.
144
inline constexpr uint32_t load32be(const uint8_t* data) noexcept
145
427k
{
146
427k
    return (uint32_t{data[0]} << 24) | (uint32_t{data[1]} << 16) | (uint32_t{data[2]} << 8) |
147
427k
           uint32_t{data[3]};
148
427k
}
149
150
/// Loads 32 bits / 4 bytes of data from the given @p data array in little-endian order.
151
inline constexpr uint32_t load32le(const uint8_t* data) noexcept
152
10.4M
{
153
10.4M
    return uint32_t{data[0]} | (uint32_t{data[1]} << 8) | (uint32_t{data[2]} << 16) |
154
10.4M
           (uint32_t{data[3]} << 24);
155
10.4M
}
156
157
namespace fnv
158
{
159
constexpr auto prime = 0x100000001b3;              ///< The 64-bit FNV prime number.
160
constexpr auto offset_basis = 0xcbf29ce484222325;  ///< The 64-bit FNV offset basis.
161
162
/// The hashing transformation for 64-bit inputs based on the FNV-1a formula.
163
inline constexpr uint64_t fnv1a_by64(uint64_t h, uint64_t x) noexcept
164
11.8M
{
165
11.8M
    return (h ^ x) * prime;
166
11.8M
}
167
}  // namespace fnv
168
169
170
/// The "equal to" comparison operator for the evmc::address type.
171
inline constexpr bool operator==(const address& a, const address& b) noexcept
172
6.34M
{
173
6.34M
    return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
174
3.62M
           load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
175
3.27M
           load32le(&a.bytes[16]) == load32le(&b.bytes[16]);
176
6.34M
}
177
178
/// The "not equal to" comparison operator for the evmc::address type.
179
inline constexpr bool operator!=(const address& a, const address& b) noexcept
180
0
{
181
0
    return !(a == b);
182
0
}
183
184
/// The "less than" comparison operator for the evmc::address type.
185
inline constexpr bool operator<(const address& a, const address& b) noexcept
186
738k
{
187
738k
    return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
188
503k
           (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) &&
189
268k
            (load64be(&a.bytes[8]) < load64be(&b.bytes[8]) ||
190
240k
             (load64be(&a.bytes[8]) == load64be(&b.bytes[8]) &&
191
213k
              load32be(&a.bytes[16]) < load32be(&b.bytes[16]))));
192
738k
}
193
194
/// The "greater than" comparison operator for the evmc::address type.
195
inline constexpr bool operator>(const address& a, const address& b) noexcept
196
0
{
197
0
    return b < a;
198
0
}
199
200
/// The "less than or equal to" comparison operator for the evmc::address type.
201
inline constexpr bool operator<=(const address& a, const address& b) noexcept
202
293k
{
203
293k
    return !(b < a);
204
293k
}
205
206
/// The "greater than or equal to" comparison operator for the evmc::address type.
207
inline constexpr bool operator>=(const address& a, const address& b) noexcept
208
444k
{
209
444k
    return !(a < b);
210
444k
}
211
212
/// The "equal to" comparison operator for the evmc::bytes32 type.
213
inline constexpr bool operator==(const bytes32& a, const bytes32& b) noexcept
214
860k
{
215
860k
    return load64le(&a.bytes[0]) == load64le(&b.bytes[0]) &&
216
814k
           load64le(&a.bytes[8]) == load64le(&b.bytes[8]) &&
217
786k
           load64le(&a.bytes[16]) == load64le(&b.bytes[16]) &&
218
765k
           load64le(&a.bytes[24]) == load64le(&b.bytes[24]);
219
860k
}
220
221
/// The "not equal to" comparison operator for the evmc::bytes32 type.
222
inline constexpr bool operator!=(const bytes32& a, const bytes32& b) noexcept
223
0
{
224
0
    return !(a == b);
225
0
}
226
227
/// The "less than" comparison operator for the evmc::bytes32 type.
228
inline constexpr bool operator<(const bytes32& a, const bytes32& b) noexcept
229
7.70M
{
230
7.70M
    return load64be(&a.bytes[0]) < load64be(&b.bytes[0]) ||
231
7.07M
           (load64be(&a.bytes[0]) == load64be(&b.bytes[0]) &&
232
6.69M
            (load64be(&a.bytes[8]) < load64be(&b.bytes[8]) ||
233
6.58M
             (load64be(&a.bytes[8]) == load64be(&b.bytes[8]) &&
234
6.51M
              (load64be(&a.bytes[16]) < load64be(&b.bytes[16]) ||
235
6.38M
               (load64be(&a.bytes[16]) == load64be(&b.bytes[16]) &&
236
6.30M
                load64be(&a.bytes[24]) < load64be(&b.bytes[24]))))));
237
7.70M
}
238
239
/// The "greater than" comparison operator for the evmc::bytes32 type.
240
inline constexpr bool operator>(const bytes32& a, const bytes32& b) noexcept
241
0
{
242
0
    return b < a;
243
0
}
244
245
/// The "less than or equal to" comparison operator for the evmc::bytes32 type.
246
inline constexpr bool operator<=(const bytes32& a, const bytes32& b) noexcept
247
0
{
248
0
    return !(b < a);
249
0
}
250
251
/// The "greater than or equal to" comparison operator for the evmc::bytes32 type.
252
inline constexpr bool operator>=(const bytes32& a, const bytes32& b) noexcept
253
0
{
254
0
    return !(a < b);
255
0
}
256
257
/// Checks if the given address is the zero address.
258
inline constexpr bool is_zero(const address& a) noexcept
259
0
{
260
0
    return a == address{};
261
0
}
262
263
inline constexpr address::operator bool() const noexcept
264
0
{
265
0
    return !is_zero(*this);
266
0
}
267
268
/// Checks if the given bytes32 object has all zero bytes.
269
inline constexpr bool is_zero(const bytes32& a) noexcept
270
198k
{
271
198k
    return a == bytes32{};
272
198k
}
273
274
inline constexpr bytes32::operator bool() const noexcept
275
98.1k
{
276
98.1k
    return !is_zero(*this);
277
98.1k
}
278
279
namespace literals
280
{
281
/// Converts a raw literal into value of type T.
282
///
283
/// This function is expected to be used on literals in constexpr context only.
284
/// In case the input is invalid the std::terminate() is called.
285
/// TODO(c++20): Use consteval.
286
template <typename T>
287
constexpr T parse(std::string_view s) noexcept
288
1.92M
{
289
1.92M
    return from_hex<T>(s).value();
290
1.92M
}
evmc::bytes32 evmc::literals::parse<evmc::bytes32>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
288
286k
{
289
286k
    return from_hex<T>(s).value();
290
286k
}
evmc::address evmc::literals::parse<evmc::address>(std::__1::basic_string_view<char, std::__1::char_traits<char> >)
Line
Count
Source
288
1.63M
{
289
1.63M
    return from_hex<T>(s).value();
290
1.63M
}
291
292
/// Literal for evmc::address.
293
constexpr address operator""_address(const char* s) noexcept
294
1.63M
{
295
1.63M
    return parse<address>(s);
296
1.63M
}
297
298
/// Literal for evmc::bytes32.
299
constexpr bytes32 operator""_bytes32(const char* s) noexcept
300
286k
{
301
286k
    return parse<bytes32>(s);
302
286k
}
303
}  // namespace literals
304
305
using namespace literals;
306
307
308
/// @copydoc evmc_status_code_to_string
309
inline const char* to_string(evmc_status_code status_code) noexcept
310
0
{
311
0
    return evmc_status_code_to_string(status_code);
312
0
}
313
314
/// @copydoc evmc_revision_to_string
315
inline const char* to_string(evmc_revision rev) noexcept
316
0
{
317
0
    return evmc_revision_to_string(rev);
318
0
}
319
320
321
/// Alias for evmc_make_result().
322
constexpr auto make_result = evmc_make_result;
323
324
/// @copydoc evmc_result
325
///
326
/// This is a RAII wrapper for evmc_result and objects of this type
327
/// automatically release attached resources.
328
class Result : private evmc_result
329
{
330
public:
331
    using evmc_result::create_address;
332
    using evmc_result::gas_left;
333
    using evmc_result::gas_refund;
334
    using evmc_result::output_data;
335
    using evmc_result::output_size;
336
    using evmc_result::status_code;
337
338
    /// Creates the result from the provided arguments.
339
    ///
340
    /// The provided output is copied to memory allocated with malloc()
341
    /// and the evmc_result::release function is set to one invoking free().
342
    ///
343
    /// @param _status_code  The status code.
344
    /// @param _gas_left     The amount of gas left.
345
    /// @param _gas_refund   The amount of refunded gas.
346
    /// @param _output_data  The pointer to the output.
347
    /// @param _output_size  The output size.
348
    explicit Result(evmc_status_code _status_code,
349
                    int64_t _gas_left,
350
                    int64_t _gas_refund,
351
                    const uint8_t* _output_data,
352
                    size_t _output_size) noexcept
353
      : evmc_result{make_result(_status_code, _gas_left, _gas_refund, _output_data, _output_size)}
354
0
    {}
355
356
    /// Creates the result without output.
357
    ///
358
    /// @param _status_code  The status code.
359
    /// @param _gas_left     The amount of gas left.
360
    /// @param _gas_refund   The amount of refunded gas.
361
    explicit Result(evmc_status_code _status_code = EVMC_INTERNAL_ERROR,
362
                    int64_t _gas_left = 0,
363
                    int64_t _gas_refund = 0) noexcept
364
4.69k
      : evmc_result{make_result(_status_code, _gas_left, _gas_refund, nullptr, 0)}
365
4.69k
    {}
366
367
    /// Creates the result of contract creation.
368
    ///
369
    /// @param _status_code     The status code.
370
    /// @param _gas_left        The amount of gas left.
371
    /// @param _gas_refund      The amount of refunded gas.
372
    /// @param _create_address  The address of the possibly created account.
373
    explicit Result(evmc_status_code _status_code,
374
                    int64_t _gas_left,
375
                    int64_t _gas_refund,
376
                    const evmc_address& _create_address) noexcept
377
      : evmc_result{make_result(_status_code, _gas_left, _gas_refund, nullptr, 0)}
378
0
    {
379
0
        create_address = _create_address;
380
0
    }
381
382
    /// Converting constructor from raw evmc_result.
383
    ///
384
    /// This object takes ownership of the resources of @p res.
385
95.1k
    explicit Result(const evmc_result& res) noexcept : evmc_result{res} {}
386
387
    /// Destructor responsible for automatically releasing attached resources.
388
    ~Result() noexcept
389
99.8k
    {
390
99.8k
        if (release != nullptr)
391
24.0k
            release(this);
392
99.8k
    }
393
394
    /// Move constructor.
395
0
    Result(Result&& other) noexcept : evmc_result{other}
396
0
    {
397
0
        other.release = nullptr;  // Disable releasing of the rvalue object.
398
0
    }
399
400
    /// Move assignment operator.
401
    ///
402
    /// The self-assignment MUST never happen.
403
    ///
404
    /// @param other The other result object.
405
    /// @return      The reference to the left-hand side object.
406
    Result& operator=(Result&& other) noexcept
407
0
    {
408
0
        this->~Result();                           // Release this object.
409
0
        static_cast<evmc_result&>(*this) = other;  // Copy data.
410
0
        other.release = nullptr;                   // Disable releasing of the rvalue object.
411
0
        return *this;
412
0
    }
413
414
    /// Access the result object as a referenced to ::evmc_result.
415
0
    evmc_result& raw() noexcept { return *this; }
416
417
    /// Access the result object as a const referenced to ::evmc_result.
418
0
    const evmc_result& raw() const noexcept { return *this; }
419
420
    /// Releases the ownership and returns the raw copy of evmc_result.
421
    ///
422
    /// This method drops the ownership of the result
423
    /// (result's resources are not going to be released when this object is destructed).
424
    /// It is the caller's responsibility having the returned copy of the result to release it.
425
    /// This object MUST NOT be used after this method is invoked.
426
    ///
427
    /// @return  The copy of this object converted to raw evmc_result.
428
    evmc_result release_raw() noexcept
429
54.3k
    {
430
54.3k
        const auto out = evmc_result{*this};  // Copy data.
431
54.3k
        this->release = nullptr;              // Disable releasing of this object.
432
54.3k
        return out;
433
54.3k
    }
434
};
435
436
437
/// The EVMC Host interface
438
class HostInterface
439
{
440
public:
441
12.1k
    virtual ~HostInterface() noexcept = default;
442
443
    /// @copydoc evmc_host_interface::account_exists
444
    virtual bool account_exists(const address& addr) const noexcept = 0;
445
446
    /// @copydoc evmc_host_interface::get_storage
447
    virtual bytes32 get_storage(const address& addr, const bytes32& key) const noexcept = 0;
448
449
    /// @copydoc evmc_host_interface::set_storage
450
    virtual evmc_storage_status set_storage(const address& addr,
451
                                            const bytes32& key,
452
                                            const bytes32& value) noexcept = 0;
453
454
    /// @copydoc evmc_host_interface::get_balance
455
    virtual uint256be get_balance(const address& addr) const noexcept = 0;
456
457
    /// @copydoc evmc_host_interface::get_code_size
458
    virtual size_t get_code_size(const address& addr) const noexcept = 0;
459
460
    /// @copydoc evmc_host_interface::get_code_hash
461
    virtual bytes32 get_code_hash(const address& addr) const noexcept = 0;
462
463
    /// @copydoc evmc_host_interface::copy_code
464
    virtual size_t copy_code(const address& addr,
465
                             size_t code_offset,
466
                             uint8_t* buffer_data,
467
                             size_t buffer_size) const noexcept = 0;
468
469
    /// @copydoc evmc_host_interface::selfdestruct
470
    virtual bool selfdestruct(const address& addr, const address& beneficiary) noexcept = 0;
471
472
    /// @copydoc evmc_host_interface::call
473
    virtual Result call(const evmc_message& msg) noexcept = 0;
474
475
    /// @copydoc evmc_host_interface::get_tx_context
476
    virtual evmc_tx_context get_tx_context() const noexcept = 0;
477
478
    /// @copydoc evmc_host_interface::get_block_hash
479
    virtual bytes32 get_block_hash(int64_t block_number) const noexcept = 0;
480
481
    /// @copydoc evmc_host_interface::emit_log
482
    virtual void emit_log(const address& addr,
483
                          const uint8_t* data,
484
                          size_t data_size,
485
                          const bytes32 topics[],
486
                          size_t num_topics) noexcept = 0;
487
488
    /// @copydoc evmc_host_interface::access_account
489
    virtual evmc_access_status access_account(const address& addr) noexcept = 0;
490
491
    /// @copydoc evmc_host_interface::access_storage
492
    virtual evmc_access_status access_storage(const address& addr, const bytes32& key) noexcept = 0;
493
494
    /// @copydoc evmc_host_interface::get_transient_storage
495
    virtual bytes32 get_transient_storage(const address& addr,
496
                                          const bytes32& key) const noexcept = 0;
497
498
    /// @copydoc evmc_host_interface::set_transient_storage
499
    virtual void set_transient_storage(const address& addr,
500
                                       const bytes32& key,
501
                                       const bytes32& value) noexcept = 0;
502
};
503
504
505
/// Wrapper around EVMC host context / host interface.
506
///
507
/// To be used by VM implementations as better alternative to using ::evmc_host_context directly.
508
class HostContext : public HostInterface
509
{
510
    const evmc_host_interface* host = nullptr;
511
    evmc_host_context* context = nullptr;
512
513
public:
514
    /// Default constructor for null Host context.
515
    HostContext() = default;
516
517
    /// Constructor from the EVMC Host primitives.
518
    /// @param interface  The reference to the Host interface.
519
    /// @param ctx        The pointer to the Host context object. This parameter MAY be null.
520
    HostContext(const evmc_host_interface& interface, evmc_host_context* ctx) noexcept
521
      : host{&interface}, context{ctx}
522
0
    {}
523
524
    bool account_exists(const address& address) const noexcept final
525
0
    {
526
0
        return host->account_exists(context, &address);
527
0
    }
528
529
    bytes32 get_storage(const address& address, const bytes32& key) const noexcept final
530
0
    {
531
0
        return host->get_storage(context, &address, &key);
532
0
    }
533
534
    evmc_storage_status set_storage(const address& address,
535
                                    const bytes32& key,
536
                                    const bytes32& value) noexcept final
537
0
    {
538
0
        return host->set_storage(context, &address, &key, &value);
539
0
    }
540
541
    uint256be get_balance(const address& address) const noexcept final
542
0
    {
543
0
        return host->get_balance(context, &address);
544
0
    }
545
546
    size_t get_code_size(const address& address) const noexcept final
547
0
    {
548
0
        return host->get_code_size(context, &address);
549
0
    }
550
551
    bytes32 get_code_hash(const address& address) const noexcept final
552
0
    {
553
0
        return host->get_code_hash(context, &address);
554
0
    }
555
556
    size_t copy_code(const address& address,
557
                     size_t code_offset,
558
                     uint8_t* buffer_data,
559
                     size_t buffer_size) const noexcept final
560
0
    {
561
0
        return host->copy_code(context, &address, code_offset, buffer_data, buffer_size);
562
0
    }
563
564
    bool selfdestruct(const address& addr, const address& beneficiary) noexcept final
565
0
    {
566
0
        return host->selfdestruct(context, &addr, &beneficiary);
567
0
    }
568
569
    Result call(const evmc_message& message) noexcept final
570
0
    {
571
0
        return Result{host->call(context, &message)};
572
0
    }
573
574
    /// @copydoc HostInterface::get_tx_context()
575
0
    evmc_tx_context get_tx_context() const noexcept final { return host->get_tx_context(context); }
576
577
    bytes32 get_block_hash(int64_t number) const noexcept final
578
0
    {
579
0
        return host->get_block_hash(context, number);
580
0
    }
581
582
    void emit_log(const address& addr,
583
                  const uint8_t* data,
584
                  size_t data_size,
585
                  const bytes32 topics[],
586
                  size_t topics_count) noexcept final
587
0
    {
588
0
        host->emit_log(context, &addr, data, data_size, topics, topics_count);
589
0
    }
590
591
    evmc_access_status access_account(const address& address) noexcept final
592
0
    {
593
0
        return host->access_account(context, &address);
594
0
    }
595
596
    evmc_access_status access_storage(const address& address, const bytes32& key) noexcept final
597
0
    {
598
0
        return host->access_storage(context, &address, &key);
599
0
    }
600
601
    bytes32 get_transient_storage(const address& address, const bytes32& key) const noexcept final
602
0
    {
603
0
        return host->get_transient_storage(context, &address, &key);
604
0
    }
605
606
    void set_transient_storage(const address& address,
607
                               const bytes32& key,
608
                               const bytes32& value) noexcept final
609
0
    {
610
0
        host->set_transient_storage(context, &address, &key, &value);
611
0
    }
612
};
613
614
615
/// Abstract class to be used by Host implementations.
616
///
617
/// When implementing EVMC Host, you can directly inherit from the evmc::Host class.
618
/// This way your implementation will be simpler by avoiding manual handling
619
/// of the ::evmc_host_context and the ::evmc_host_interface.
620
class Host : public HostInterface
621
{
622
public:
623
    /// Provides access to the global host interface.
624
    /// @returns  Reference to the host interface object.
625
    static const evmc_host_interface& get_interface() noexcept;
626
627
    /// Converts the Host object to the opaque host context pointer.
628
    /// @returns  Pointer to evmc_host_context.
629
95.1k
    evmc_host_context* to_context() noexcept { return reinterpret_cast<evmc_host_context*>(this); }
630
631
    /// Converts the opaque host context pointer back to the original Host object.
632
    /// @tparam DerivedClass  The class derived from the Host class.
633
    /// @param context        The opaque host context pointer.
634
    /// @returns              The pointer to DerivedClass.
635
    template <typename DerivedClass = Host>
636
    static DerivedClass* from_context(evmc_host_context* context) noexcept
637
2.06M
    {
638
        // Get pointer of the Host base class.
639
2.06M
        auto* h = reinterpret_cast<Host*>(context);
640
641
        // Additional downcast, only possible if DerivedClass inherits from Host.
642
2.06M
        return static_cast<DerivedClass*>(h);
643
2.06M
    }
644
};
645
646
647
/// @copybrief evmc_vm
648
///
649
/// This is a RAII wrapper for evmc_vm, and object of this type
650
/// automatically destroys the VM instance.
651
class VM
652
{
653
public:
654
    VM() noexcept = default;
655
656
    /// Converting constructor from evmc_vm.
657
8
    explicit VM(evmc_vm* vm) noexcept : m_instance{vm} {}
658
659
    /// Destructor responsible for automatically destroying the VM instance.
660
    ~VM() noexcept
661
0
    {
662
0
        if (m_instance != nullptr)
663
0
            m_instance->destroy(m_instance);
664
0
    }
665
666
    VM(const VM&) = delete;
667
    VM& operator=(const VM&) = delete;
668
669
    /// Move constructor.
670
0
    VM(VM&& other) noexcept : m_instance{other.m_instance} { other.m_instance = nullptr; }
671
672
    /// Move assignment operator.
673
    VM& operator=(VM&& other) noexcept
674
0
    {
675
0
        this->~VM();
676
0
        m_instance = other.m_instance;
677
0
        other.m_instance = nullptr;
678
0
        return *this;
679
0
    }
680
681
    /// The constructor that captures a VM instance and configures the instance
682
    /// with the provided list of options.
683
    inline VM(evmc_vm* vm,
684
              std::initializer_list<std::pair<const char*, const char*>> options) noexcept;
685
686
    /// Checks if contains a valid pointer to the VM instance.
687
12.1k
    explicit operator bool() const noexcept { return m_instance != nullptr; }
688
689
    /// Checks whenever the VM instance is ABI compatible with the current EVMC API.
690
0
    bool is_abi_compatible() const noexcept { return m_instance->abi_version == EVMC_ABI_VERSION; }
691
692
    /// @copydoc evmc_vm::name
693
0
    char const* name() const noexcept { return m_instance->name; }
694
695
    /// @copydoc evmc_vm::version
696
0
    char const* version() const noexcept { return m_instance->version; }
697
698
    /// Checks if the VM has the given capability.
699
    bool has_capability(evmc_capabilities capability) const noexcept
700
0
    {
701
0
        return (get_capabilities() & static_cast<evmc_capabilities_flagset>(capability)) != 0;
702
0
    }
703
704
    /// @copydoc evmc_vm::get_capabilities
705
    evmc_capabilities_flagset get_capabilities() const noexcept
706
0
    {
707
0
        return m_instance->get_capabilities(m_instance);
708
0
    }
709
710
    /// @copydoc evmc_set_option()
711
    evmc_set_option_result set_option(const char name[], const char value[]) noexcept
712
0
    {
713
0
        return evmc_set_option(m_instance, name, value);
714
0
    }
715
716
    /// @copydoc evmc_execute()
717
    Result execute(const evmc_host_interface& host,
718
                   evmc_host_context* ctx,
719
                   evmc_revision rev,
720
                   const evmc_message& msg,
721
                   const uint8_t* code,
722
                   size_t code_size) noexcept
723
95.1k
    {
724
95.1k
        return Result{m_instance->execute(m_instance, &host, ctx, rev, &msg, code, code_size)};
725
95.1k
    }
726
727
    /// Convenient variant of the VM::execute() that takes reference to evmc::Host class.
728
    Result execute(Host& host,
729
                   evmc_revision rev,
730
                   const evmc_message& msg,
731
                   const uint8_t* code,
732
                   size_t code_size) noexcept
733
95.1k
    {
734
95.1k
        return execute(Host::get_interface(), host.to_context(), rev, msg, code, code_size);
735
95.1k
    }
736
737
    /// Executes code without the Host context.
738
    ///
739
    /// The same as
740
    /// execute(const evmc_host_interface&, evmc_host_context*, evmc_revision,
741
    ///         const evmc_message&, const uint8_t*, size_t),
742
    /// but without providing the Host context and interface.
743
    /// This method is for experimental precompiles support where execution is
744
    /// guaranteed not to require any Host access.
745
    Result execute(evmc_revision rev,
746
                   const evmc_message& msg,
747
                   const uint8_t* code,
748
                   size_t code_size) noexcept
749
0
    {
750
0
        return Result{
751
0
            m_instance->execute(m_instance, nullptr, nullptr, rev, &msg, code, code_size)};
752
0
    }
753
754
    /// Returns the pointer to C EVMC struct representing the VM.
755
    ///
756
    /// Gives access to the C EVMC VM struct to allow advanced interaction with the VM not supported
757
    /// by the C++ interface. Use as the last resort.
758
    /// This object still owns the VM after returning the pointer. The returned pointer MAY be null.
759
0
    evmc_vm* get_raw_pointer() const noexcept { return m_instance; }
760
761
private:
762
    evmc_vm* m_instance = nullptr;
763
};
764
765
inline VM::VM(evmc_vm* vm,
766
              std::initializer_list<std::pair<const char*, const char*>> options) noexcept
767
  : m_instance{vm}
768
{
769
    // This constructor is implemented outside of the class definition to workaround a doxygen bug.
770
    for (const auto& option : options)
771
        set_option(option.first, option.second);
772
}
773
774
775
namespace internal
776
{
777
inline bool account_exists(evmc_host_context* h, const evmc_address* addr) noexcept
778
99.5k
{
779
99.5k
    return Host::from_context(h)->account_exists(*addr);
780
99.5k
}
781
782
inline evmc_bytes32 get_storage(evmc_host_context* h,
783
                                const evmc_address* addr,
784
                                const evmc_bytes32* key) noexcept
785
191k
{
786
191k
    return Host::from_context(h)->get_storage(*addr, *key);
787
191k
}
788
789
inline evmc_storage_status set_storage(evmc_host_context* h,
790
                                       const evmc_address* addr,
791
                                       const evmc_bytes32* key,
792
                                       const evmc_bytes32* value) noexcept
793
533k
{
794
533k
    return Host::from_context(h)->set_storage(*addr, *key, *value);
795
533k
}
796
797
inline evmc_uint256be get_balance(evmc_host_context* h, const evmc_address* addr) noexcept
798
106k
{
799
106k
    return Host::from_context(h)->get_balance(*addr);
800
106k
}
801
802
inline size_t get_code_size(evmc_host_context* h, const evmc_address* addr) noexcept
803
0
{
804
0
    return Host::from_context(h)->get_code_size(*addr);
805
0
}
806
807
inline evmc_bytes32 get_code_hash(evmc_host_context* h, const evmc_address* addr) noexcept
808
0
{
809
0
    return Host::from_context(h)->get_code_hash(*addr);
810
0
}
811
812
inline size_t copy_code(evmc_host_context* h,
813
                        const evmc_address* addr,
814
                        size_t code_offset,
815
                        uint8_t* buffer_data,
816
                        size_t buffer_size) noexcept
817
158k
{
818
158k
    return Host::from_context(h)->copy_code(*addr, code_offset, buffer_data, buffer_size);
819
158k
}
820
821
inline bool selfdestruct(evmc_host_context* h,
822
                         const evmc_address* addr,
823
                         const evmc_address* beneficiary) noexcept
824
436
{
825
436
    return Host::from_context(h)->selfdestruct(*addr, *beneficiary);
826
436
}
827
828
inline evmc_result call(evmc_host_context* h, const evmc_message* msg) noexcept
829
54.3k
{
830
54.3k
    return Host::from_context(h)->call(*msg).release_raw();
831
54.3k
}
832
833
inline evmc_tx_context get_tx_context(evmc_host_context* h) noexcept
834
20.1k
{
835
20.1k
    return Host::from_context(h)->get_tx_context();
836
20.1k
}
837
838
inline evmc_bytes32 get_block_hash(evmc_host_context* h, int64_t block_number) noexcept
839
0
{
840
0
    return Host::from_context(h)->get_block_hash(block_number);
841
0
}
842
843
inline void emit_log(evmc_host_context* h,
844
                     const evmc_address* addr,
845
                     const uint8_t* data,
846
                     size_t data_size,
847
                     const evmc_bytes32 topics[],
848
                     size_t num_topics) noexcept
849
0
{
850
0
    Host::from_context(h)->emit_log(*addr, data, data_size, static_cast<const bytes32*>(topics),
851
0
                                    num_topics);
852
0
}
853
854
inline evmc_access_status access_account(evmc_host_context* h, const evmc_address* addr) noexcept
855
158k
{
856
158k
    return Host::from_context(h)->access_account(*addr);
857
158k
}
858
859
inline evmc_access_status access_storage(evmc_host_context* h,
860
                                         const evmc_address* addr,
861
                                         const evmc_bytes32* key) noexcept
862
724k
{
863
724k
    return Host::from_context(h)->access_storage(*addr, *key);
864
724k
}
865
866
inline evmc_bytes32 get_transient_storage(evmc_host_context* h,
867
                                          const evmc_address* addr,
868
                                          const evmc_bytes32* key) noexcept
869
2.51k
{
870
2.51k
    return Host::from_context(h)->get_transient_storage(*addr, *key);
871
2.51k
}
872
873
inline void set_transient_storage(evmc_host_context* h,
874
                                  const evmc_address* addr,
875
                                  const evmc_bytes32* key,
876
                                  const evmc_bytes32* value) noexcept
877
15.8k
{
878
15.8k
    Host::from_context(h)->set_transient_storage(*addr, *key, *value);
879
15.8k
}
880
}  // namespace internal
881
882
inline const evmc_host_interface& Host::get_interface() noexcept
883
95.1k
{
884
95.1k
    static constexpr evmc_host_interface interface = {
885
95.1k
        ::evmc::internal::account_exists,
886
95.1k
        ::evmc::internal::get_storage,
887
95.1k
        ::evmc::internal::set_storage,
888
95.1k
        ::evmc::internal::get_balance,
889
95.1k
        ::evmc::internal::get_code_size,
890
95.1k
        ::evmc::internal::get_code_hash,
891
95.1k
        ::evmc::internal::copy_code,
892
95.1k
        ::evmc::internal::selfdestruct,
893
95.1k
        ::evmc::internal::call,
894
95.1k
        ::evmc::internal::get_tx_context,
895
95.1k
        ::evmc::internal::get_block_hash,
896
95.1k
        ::evmc::internal::emit_log,
897
95.1k
        ::evmc::internal::access_account,
898
95.1k
        ::evmc::internal::access_storage,
899
95.1k
        ::evmc::internal::get_transient_storage,
900
95.1k
        ::evmc::internal::set_transient_storage,
901
95.1k
    };
902
95.1k
    return interface;
903
95.1k
}
904
}  // namespace evmc
905
906
907
/// "Stream out" operator implementation for ::evmc_status_code.
908
///
909
/// @note This is defined in global namespace to match ::evmc_status_code definition and allow
910
///       convenient operator overloading usage.
911
inline std::ostream& operator<<(std::ostream& os, evmc_status_code status_code)
912
0
{
913
0
    return os << evmc::to_string(status_code);
914
0
}
915
916
/// "Stream out" operator implementation for ::evmc_revision.
917
///
918
/// @note This is defined in global namespace to match ::evmc_revision definition and allow
919
///       convenient operator overloading usage.
920
inline std::ostream& operator<<(std::ostream& os, evmc_revision rev)
921
0
{
922
0
    return os << evmc::to_string(rev);
923
0
}
924
925
namespace std
926
{
927
/// Hash operator template specialization for evmc::address. Needed for unordered containers.
928
template <>
929
struct hash<evmc::address>
930
{
931
    /// Hash operator using FNV1a-based folding.
932
    constexpr size_t operator()(const evmc::address& s) const noexcept
933
3.93M
    {
934
3.93M
        using namespace evmc;
935
3.93M
        using namespace fnv;
936
3.93M
        return static_cast<size_t>(fnv1a_by64(
937
3.93M
            fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])), load64le(&s.bytes[8])),
938
3.93M
            load32le(&s.bytes[16])));
939
3.93M
    }
940
};
941
942
/// Hash operator template specialization for evmc::bytes32. Needed for unordered containers.
943
template <>
944
struct hash<evmc::bytes32>
945
{
946
    /// Hash operator using FNV1a-based folding.
947
    constexpr size_t operator()(const evmc::bytes32& s) const noexcept
948
19.7k
    {
949
19.7k
        using namespace evmc;
950
19.7k
        using namespace fnv;
951
19.7k
        return static_cast<size_t>(
952
19.7k
            fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv1a_by64(fnv::offset_basis, load64le(&s.bytes[0])),
953
19.7k
                                             load64le(&s.bytes[8])),
954
19.7k
                                  load64le(&s.bytes[16])),
955
19.7k
                       load64le(&s.bytes[24])));
956
19.7k
    }
957
};
958
}  // namespace std