Coverage Report

Created: 2026-07-13 07:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/solidity/test/EVMHost.cpp
Line
Count
Source
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * EVM execution host, i.e. component that implements a simulated Ethereum blockchain
20
 * for testing purposes.
21
 */
22
23
// Weird issue when compiling with O3 on gcc 12 and later due to usage of vector<uint8_t> (aka bytes) as std::map key
24
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98465
25
// also clang doesn't know stringop-overread
26
#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma
27
#pragma GCC diagnostic push
28
#pragma GCC diagnostic ignored "-Wstringop-overread"
29
#endif
30
31
#include <test/EVMHost.h>
32
#include <test/libsolidity/util/SoltestErrors.h>
33
34
#if defined(__GNUC__) && !defined(__clang__) // GCC-specific pragma
35
#pragma GCC diagnostic pop
36
#endif
37
38
#include <test/evmc/loader.h>
39
40
#include <libevmasm/GasMeter.h>
41
42
#include <libsolutil/Exceptions.h>
43
#include <libsolutil/Assertions.h>
44
#include <libsolutil/Keccak256.h>
45
#include <libsolutil/picosha2.h>
46
47
using namespace solidity;
48
using namespace solidity::util;
49
using namespace solidity::test;
50
using namespace evmc::literals;
51
52
evmc::VM& EVMHost::getVM(std::string const& _path)
53
0
{
54
0
  static evmc::VM NullVM{nullptr};
55
0
  static std::map<std::string, std::unique_ptr<evmc::VM>> vms;
56
0
  if (vms.count(_path) == 0)
57
0
  {
58
0
    evmc_loader_error_code errorCode = {};
59
0
    auto vm = evmc::VM{evmc_load_and_configure(_path.c_str(), &errorCode)};
60
0
    if (vm && errorCode == EVMC_LOADER_SUCCESS)
61
0
    {
62
0
      if (vm.get_capabilities() & (EVMC_CAPABILITY_EVM1))
63
0
        vms[_path] = std::make_unique<evmc::VM>(evmc::VM(std::move(vm)));
64
0
      else
65
0
        std::cerr << "VM loaded does not support EVM1" << std::endl;
66
0
    }
67
0
    else
68
0
    {
69
0
      std::cerr << "Error loading VM from " << _path;
70
0
      if (char const* errorMsg = evmc_last_error_msg())
71
0
        std::cerr << ":" << std::endl << errorMsg;
72
0
      std::cerr << std::endl;
73
0
    }
74
0
  }
75
76
0
  if (vms.count(_path) > 0)
77
0
    return *vms[_path];
78
79
0
  return NullVM;
80
0
}
81
82
bool EVMHost::checkVmPaths(std::vector<boost::filesystem::path> const& _vmPaths)
83
0
{
84
0
  bool evmVmFound = false;
85
0
  for (auto const& path: _vmPaths)
86
0
  {
87
0
    evmc::VM& vm = EVMHost::getVM(path.string());
88
0
    if (!vm)
89
0
      continue;
90
91
0
    if (vm.has_capability(EVMC_CAPABILITY_EVM1))
92
0
    {
93
0
      if (evmVmFound)
94
0
        BOOST_THROW_EXCEPTION(std::runtime_error("Multiple evm1 evmc vms defined. Please only define one evm1 evmc vm."));
95
0
      evmVmFound = true;
96
0
    }
97
0
  }
98
0
  return evmVmFound;
99
0
}
100
101
EVMHost::EVMHost(langutil::EVMVersion _evmVersion, evmc::VM& _vm):
102
12.2k
  m_vm(_vm),
103
12.2k
  m_evmVersion(_evmVersion)
104
12.2k
{
105
12.2k
  if (!m_vm)
106
0
  {
107
0
    std::cerr << "Unable to find evmone library" << std::endl;
108
0
    solRequire(false, Exception, "");
109
0
  }
110
111
12.2k
  if (_evmVersion == langutil::EVMVersion::homestead())
112
0
    m_evmRevision = EVMC_HOMESTEAD;
113
12.2k
  else if (_evmVersion == langutil::EVMVersion::tangerineWhistle())
114
0
    m_evmRevision = EVMC_TANGERINE_WHISTLE;
115
12.2k
  else if (_evmVersion == langutil::EVMVersion::spuriousDragon())
116
0
    m_evmRevision = EVMC_SPURIOUS_DRAGON;
117
12.2k
  else if (_evmVersion == langutil::EVMVersion::byzantium())
118
0
    m_evmRevision = EVMC_BYZANTIUM;
119
12.2k
  else if (_evmVersion == langutil::EVMVersion::constantinople())
120
0
    m_evmRevision = EVMC_CONSTANTINOPLE;
121
12.2k
  else if (_evmVersion == langutil::EVMVersion::petersburg())
122
0
    m_evmRevision = EVMC_PETERSBURG;
123
12.2k
  else if (_evmVersion == langutil::EVMVersion::istanbul())
124
0
    m_evmRevision = EVMC_ISTANBUL;
125
12.2k
  else if (_evmVersion == langutil::EVMVersion::berlin())
126
0
    m_evmRevision = EVMC_BERLIN;
127
12.2k
  else if (_evmVersion == langutil::EVMVersion::london())
128
0
    m_evmRevision = EVMC_LONDON;
129
12.2k
  else if (_evmVersion == langutil::EVMVersion::paris())
130
0
    m_evmRevision = EVMC_PARIS;
131
12.2k
  else if (_evmVersion == langutil::EVMVersion::shanghai())
132
0
    m_evmRevision = EVMC_SHANGHAI;
133
12.2k
  else if (_evmVersion == langutil::EVMVersion::cancun())
134
0
    m_evmRevision = EVMC_CANCUN;
135
12.2k
  else if (_evmVersion == langutil::EVMVersion::prague())
136
0
    m_evmRevision = EVMC_PRAGUE;
137
12.2k
  else if (_evmVersion == langutil::EVMVersion::osaka())
138
12.2k
    m_evmRevision = EVMC_OSAKA;
139
0
  else if (_evmVersion == langutil::EVMVersion::amsterdam())
140
0
    m_evmRevision = EVMC_AMSTERDAM;
141
0
  else if (_evmVersion == langutil::EVMVersion::future())
142
0
    m_evmRevision = EVMC_MAX_REVISION;
143
0
  else
144
0
    solRequire(false, Exception, "Unsupported EVM version");
145
146
12.2k
  if (m_evmRevision >= EVMC_PARIS)
147
    // This is the value from the merge block.
148
12.2k
    tx_context.block_prev_randao = 0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777_bytes32;
149
0
  else
150
0
    tx_context.block_prev_randao = evmc::uint256be{200000000};
151
12.2k
  tx_context.block_gas_limit = 20000000;
152
12.2k
  tx_context.block_coinbase = 0x7878787878787878787878787878787878787878_address;
153
12.2k
  tx_context.tx_gas_price = evmc::uint256be{3000000000};
154
12.2k
  tx_context.tx_origin = 0x9292929292929292929292929292929292929292_address;
155
  // Mainnet according to EIP-155
156
12.2k
  tx_context.chain_id = evmc::uint256be{1};
157
  // The minimum value of basefee
158
12.2k
  tx_context.block_base_fee = evmc::bytes32{7};
159
  // The minimum value of blobbasefee
160
12.2k
  tx_context.blob_base_fee = evmc::bytes32{1};
161
162
12.2k
  static evmc_bytes32 const blob_hashes_array[] = {
163
12.2k
    0x0100000000000000000000000000000000000000000000000000000000000001_bytes32,
164
12.2k
    0x0100000000000000000000000000000000000000000000000000000000000002_bytes32
165
12.2k
  };
166
12.2k
  tx_context.blob_hashes = blob_hashes_array;
167
12.2k
  tx_context.blob_hashes_count = sizeof(blob_hashes_array) / sizeof(blob_hashes_array[0]);
168
169
  // Reserve space for recording calls.
170
12.2k
  if (!recorded_calls.capacity())
171
12.2k
    recorded_calls.reserve(max_recorded_calls);
172
173
12.2k
  reset();
174
12.2k
}
175
176
void EVMHost::reset()
177
34.8k
{
178
34.8k
  accounts.clear();
179
  // Clear self destruct records
180
34.8k
  recorded_selfdestructs.clear();
181
  // Clear call records
182
34.8k
  recorded_calls.clear();
183
  // Clear EIP-2929 account access indicator
184
34.8k
  recorded_account_accesses.clear();
185
34.8k
  m_newlyCreatedAccounts.clear();
186
34.8k
  m_totalCodeDepositGas = 0;
187
188
  // Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161).
189
  // NOTE: keep this in sync with `EVMHost::call` below.
190
  //
191
  // A lot of precompile addresses had a balance before they became valid addresses for precompiles.
192
  // For example all the precompile addresses allocated in Byzantium had a 1 wei balance sent to them
193
  // roughly 22 days before the update went live.
194
313k
  for (unsigned precompiledAddress = 1; precompiledAddress <= 8; precompiledAddress++)
195
278k
  {
196
278k
    evmc::address address{precompiledAddress};
197
    // 1wei
198
278k
    accounts[address].balance = evmc::uint256be{1};
199
    // Set according to EIP-1052.
200
278k
    if (precompiledAddress < 5 || m_evmVersion >= langutil::EVMVersion::byzantium())
201
278k
      accounts[address].codehash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470_bytes32;
202
278k
  }
203
34.8k
}
204
205
void EVMHost::newTransactionFrame()
206
0
{
207
  // Clear EIP-2929 account access indicator
208
0
  recorded_account_accesses.clear();
209
210
0
  for (auto& [address, account]: accounts)
211
0
  {
212
0
    for (auto& [slot, value]: account.storage)
213
0
    {
214
0
      value.access_status = EVMC_ACCESS_COLD; // Clear EIP-2929 storage access indicator
215
0
      value.original = value.current;         // Clear EIP-2200 dirty slot
216
0
    }
217
218
    // Clear transient storage according to EIP 1153
219
0
    account.transient_storage.clear();
220
0
  }
221
  // Process selfdestruct list
222
0
  for (auto& [address, _]: recorded_selfdestructs)
223
0
    if (m_evmVersion < langutil::EVMVersion::cancun() || m_newlyCreatedAccounts.count(address))
224
      // EIP-6780: If SELFDESTRUCT is executed in a transaction different from the one
225
      // in which it was created, we do NOT record it or clear any data.
226
      // Otherwise, the previous behavior (pre-Cancun) is maintained.
227
0
      accounts.erase(address);
228
0
  m_newlyCreatedAccounts.clear();
229
0
  m_totalCodeDepositGas = 0;
230
0
  recorded_selfdestructs.clear();
231
0
}
232
233
void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept
234
518
{
235
518
  solRequire(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer");
236
518
  _sender.balance = convertToEVMC(u256(convertFromEVMC(_sender.balance)) - _value);
237
518
  _recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value);
238
518
}
239
240
bool EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept
241
518
{
242
  // TODO actual selfdestruct is even more complicated.
243
244
  // NOTE: EIP-6780: The transfer of the entire account balance to the beneficiary should still happen
245
  // after cancun.
246
518
  transfer(accounts[_addr], accounts[_beneficiary], convertFromEVMC(accounts[_addr].balance));
247
248
  // Record self destructs. Clearing will be done in newTransactionFrame().
249
518
  return MockedHost::selfdestruct(_addr, _beneficiary);
250
518
}
251
252
void EVMHost::recordCalls(evmc_message const& _message) noexcept
253
99.3k
{
254
99.3k
  if (recorded_calls.size() < max_recorded_calls)
255
78.8k
    recorded_calls.emplace_back(_message);
256
99.3k
}
257
258
// NOTE: this is used for both internal and external calls.
259
// External calls are triggered from ExecutionFramework and contain only EVMC_CREATE or EVMC_CALL.
260
evmc::Result EVMHost::call(evmc_message const& _message) noexcept
261
99.3k
{
262
99.3k
  recordCalls(_message);
263
99.3k
  if (_message.recipient == 0x0000000000000000000000000000000000000001_address)
264
0
    return precompileECRecover(_message);
265
99.3k
  else if (_message.recipient == 0x0000000000000000000000000000000000000002_address)
266
837
    return precompileSha256(_message);
267
98.4k
  else if (_message.recipient == 0x0000000000000000000000000000000000000003_address)
268
1.04k
    return precompileRipeMD160(_message);
269
97.4k
  else if (_message.recipient == 0x0000000000000000000000000000000000000004_address)
270
935
    return precompileIdentity(_message);
271
96.4k
  else if (_message.recipient == 0x0000000000000000000000000000000000000005_address && m_evmVersion >= langutil::EVMVersion::byzantium())
272
263
    return precompileModExp(_message);
273
96.2k
  else if (_message.recipient == 0x0000000000000000000000000000000000000006_address && m_evmVersion >= langutil::EVMVersion::byzantium())
274
0
  {
275
0
    if (m_evmVersion <= langutil::EVMVersion::istanbul())
276
0
      return precompileALTBN128G1Add<EVMC_ISTANBUL>(_message);
277
0
    else
278
0
      return precompileALTBN128G1Add<EVMC_LONDON>(_message);
279
0
  }
280
96.2k
  else if (_message.recipient == 0x0000000000000000000000000000000000000007_address && m_evmVersion >= langutil::EVMVersion::byzantium())
281
0
  {
282
0
    if (m_evmVersion <= langutil::EVMVersion::istanbul())
283
0
      return precompileALTBN128G1Mul<EVMC_ISTANBUL>(_message);
284
0
    else
285
0
      return precompileALTBN128G1Mul<EVMC_LONDON>(_message);
286
0
  }
287
96.2k
  else if (_message.recipient == 0x0000000000000000000000000000000000000008_address && m_evmVersion >= langutil::EVMVersion::byzantium())
288
0
  {
289
0
    if (m_evmVersion <= langutil::EVMVersion::istanbul())
290
0
      return precompileALTBN128PairingProduct<EVMC_ISTANBUL>(_message);
291
0
    else
292
0
      return precompileALTBN128PairingProduct<EVMC_LONDON>(_message);
293
0
  }
294
96.2k
  else if (_message.recipient == 0x0000000000000000000000000000000000000009_address && m_evmVersion >= langutil::EVMVersion::istanbul())
295
20
    return precompileBlake2f(_message);
296
297
96.2k
  auto const stateBackup = accounts;
298
299
96.2k
  u256 value{convertFromEVMC(_message.value)};
300
96.2k
  auto& sender = accounts[_message.sender];
301
302
96.2k
  evmc::bytes code;
303
304
96.2k
  evmc_message message = _message;
305
96.2k
  if (message.depth == 0)
306
46.1k
  {
307
46.1k
    message.gas -= message.kind == EVMC_CREATE ? evmasm::GasCosts::txCreateGas : evmasm::GasCosts::txGas;
308
18.7M
    for (size_t i = 0; i < message.input_size; ++i)
309
18.6M
      message.gas -= message.input_data[i] == 0 ? evmasm::GasCosts::txDataZeroGas : evmasm::GasCosts::txDataNonZeroGas(m_evmVersion);
310
46.1k
    if (message.gas < 0)
311
0
    {
312
0
      evmc::Result result;
313
0
      result.status_code = EVMC_OUT_OF_GAS;
314
0
      accounts = stateBackup;
315
0
      return result;
316
0
    }
317
46.1k
  }
318
319
96.2k
  if (message.kind == EVMC_CREATE)
320
23.0k
  {
321
    // TODO is the nonce incremented on failure, too?
322
    // NOTE: nonce for creation from contracts starts at 1
323
    // TODO: check if sender is an EOA and do not pre-increment
324
23.0k
    sender.nonce++;
325
326
23.0k
    auto encodeRlpInteger = [](int value) -> bytes {
327
23.0k
      if (value == 0) {
328
0
        return bytes{128};
329
23.0k
      } else if (value <= 127) {
330
23.0k
        return bytes{static_cast<uint8_t>(value)};
331
23.0k
      } else if (value <= 0xff) {
332
0
        return bytes{128 + 1, static_cast<uint8_t>(value)};
333
0
      } else if (value <= 0xffff) {
334
0
        return bytes{128 + 55 + 2, static_cast<uint8_t>(value >> 8), static_cast<uint8_t>(value)};
335
0
      } else {
336
0
        solUnimplemented("Can only encode RLP numbers <= 0xffff");
337
0
      }
338
23.0k
    };
339
340
23.0k
    bytes encodedNonce = encodeRlpInteger(sender.nonce);
341
342
23.0k
    h160 createAddress(keccak256(
343
23.0k
      bytes{static_cast<uint8_t>(0xc0 + 21 + encodedNonce.size())} +
344
23.0k
      bytes{0x94} +
345
23.0k
      bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) +
346
23.0k
      encodedNonce
347
23.0k
    ), h160::AlignRight);
348
349
23.0k
    message.recipient = convertToEVMC(createAddress);
350
23.0k
    soltestAssert(accounts.count(message.recipient) == 0, "Account cannot exist");
351
352
23.0k
    code = evmc::bytes(message.input_data, message.input_data + message.input_size);
353
23.0k
  }
354
73.1k
  else if (message.kind == EVMC_CREATE2)
355
0
  {
356
0
    h160 createAddress(keccak256(
357
0
      bytes{0xff} +
358
0
      bytes(std::begin(message.sender.bytes), std::end(message.sender.bytes)) +
359
0
      bytes(std::begin(message.create2_salt.bytes), std::end(message.create2_salt.bytes)) +
360
0
      keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes()
361
0
    ), h160::AlignRight);
362
363
0
    message.recipient = convertToEVMC(createAddress);
364
0
    if (accounts.count(message.recipient) && (
365
0
      accounts[message.recipient].nonce > 0 ||
366
0
      !accounts[message.recipient].code.empty()
367
0
    ))
368
0
    {
369
0
      evmc::Result result;
370
0
      result.status_code = EVMC_OUT_OF_GAS;
371
0
      accounts = stateBackup;
372
0
      return result;
373
0
    }
374
375
376
0
    code = evmc::bytes(message.input_data, message.input_data + message.input_size);
377
0
  }
378
73.1k
  else
379
73.1k
    code = accounts[message.code_address].code;
380
381
96.2k
  auto& destination = accounts[message.recipient];
382
96.2k
  if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2)
383
    // Mark account as created if it is a CREATE or CREATE2 call
384
    // TODO: Should we roll changes back on failure like we do for `accounts`?
385
23.0k
    m_newlyCreatedAccounts.emplace(message.recipient);
386
387
96.2k
  if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE)
388
0
  {
389
0
    if (value > convertFromEVMC(sender.balance))
390
0
    {
391
0
      evmc::Result result;
392
0
      result.status_code = EVMC_INSUFFICIENT_BALANCE;
393
0
      accounts = stateBackup;
394
0
      return result;
395
0
    }
396
0
    transfer(sender, destination, value);
397
0
  }
398
399
  // Populate the access list (enabled since Berlin).
400
  // Note, this will also properly touch the created address.
401
  // TODO: support a user supplied access list too
402
96.2k
  if (m_evmRevision >= EVMC_BERLIN)
403
96.2k
  {
404
96.2k
    access_account(message.sender);
405
96.2k
    access_account(message.recipient);
406
407
    // EIP-3651 rule
408
96.2k
    if (m_evmRevision >= EVMC_SHANGHAI)
409
96.2k
      access_account(tx_context.block_coinbase);
410
96.2k
  }
411
412
96.2k
  if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2)
413
23.0k
  {
414
23.0k
    message.input_data = nullptr;
415
23.0k
    message.input_size = 0;
416
23.0k
  }
417
96.2k
  evmc::Result result = m_vm.execute(*this, m_evmRevision, message, code.data(), code.size());
418
419
96.2k
  if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2)
420
23.0k
  {
421
23.0k
    int64_t codeDepositGas = static_cast<int64_t>(evmasm::GasCosts::createDataGas * result.output_size);
422
23.0k
    result.gas_left -= codeDepositGas;
423
23.0k
    if (result.gas_left < 0)
424
0
    {
425
0
      m_totalCodeDepositGas += -result.gas_left;
426
0
      result.gas_left = 0;
427
0
      result.status_code = EVMC_OUT_OF_GAS;
428
      // TODO clear some fields?
429
0
    }
430
23.0k
    else
431
23.0k
    {
432
23.0k
      m_totalCodeDepositGas += codeDepositGas;
433
23.0k
      result.create_address = message.recipient;
434
23.0k
      destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size);
435
23.0k
      destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size}));
436
23.0k
    }
437
23.0k
  }
438
439
96.2k
  if (result.status_code != EVMC_SUCCESS)
440
1.34k
    accounts = stateBackup;
441
442
96.2k
  return result;
443
96.2k
}
444
445
evmc::bytes32 EVMHost::get_block_hash(int64_t _number) const noexcept
446
0
{
447
0
  return convertToEVMC(u256("0x3737373737373737373737373737373737373737373737373737373737373737") + _number);
448
0
}
449
450
h160 EVMHost::convertFromEVMC(evmc::address const& _addr)
451
0
{
452
0
  return h160(bytes(std::begin(_addr.bytes), std::end(_addr.bytes)));
453
0
}
454
455
evmc::address EVMHost::convertToEVMC(h160 const& _addr)
456
23.0k
{
457
23.0k
  evmc::address a;
458
484k
  for (unsigned i = 0; i < 20; ++i)
459
461k
    a.bytes[i] = _addr[i];
460
23.0k
  return a;
461
23.0k
}
462
463
h256 EVMHost::convertFromEVMC(evmc::bytes32 const& _data)
464
281k
{
465
281k
  return h256(bytes(std::begin(_data.bytes), std::end(_data.bytes)));
466
281k
}
467
468
evmc::bytes32 EVMHost::convertToEVMC(h256 const& _data)
469
24.1k
{
470
24.1k
  evmc::bytes32 d;
471
795k
  for (unsigned i = 0; i < 32; ++i)
472
771k
    d.bytes[i] = _data[i];
473
24.1k
  return d;
474
24.1k
}
475
476
evmc::Result EVMHost::precompileECRecover(evmc_message const& _message) noexcept
477
0
{
478
  // NOTE this is a partial implementation for some inputs.
479
480
  // Fixed cost of 3000 gas.
481
0
  constexpr int64_t gas_cost = 3000;
482
483
0
  static std::map<bytes, EVMPrecompileOutput> const inputOutput{
484
0
    {
485
0
      fromHex(
486
0
        "18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"
487
0
        "000000000000000000000000000000000000000000000000000000000000001c"
488
0
        "73b1693892219d736caba55bdb67216e485557ea6b6af75f37096c9aa6a5a75f"
489
0
        "eeb940b1d03b21e36b0e47e79769f095fe2ab855bd91e3a38756b7d75a9c4549"
490
0
      ),
491
0
      {
492
0
        fromHex("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
493
0
        gas_cost
494
0
      }
495
0
    },
496
0
    {
497
0
      fromHex(
498
0
        "47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad"
499
0
        "000000000000000000000000000000000000000000000000000000000000001c"
500
0
        "debaaa0cddb321b2dcaaf846d39605de7b97e77ba6106587855b9106cb104215"
501
0
        "61a22d94fa8b8a687ff9c911c844d1c016d1a685a9166858f9c7c1bc85128aca"
502
0
      ),
503
0
      {
504
0
        fromHex("0000000000000000000000008743523d96a1b2cbe0c6909653a56da18ed484af"),
505
0
        gas_cost
506
0
      }
507
0
    },
508
0
    {
509
0
      fromHex(
510
0
        "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
511
0
        "0000000000000000000000000000000000000000000000000000000000000001"
512
0
        "0000000000000000000000000000000000000000000000000000000000000002"
513
0
        "0000000000000000000000000000000000000000000000000000000000000003"
514
0
      ),
515
0
      {
516
0
        fromHex(""),
517
0
        gas_cost
518
0
      }
519
0
    },
520
0
    {
521
0
      fromHex(
522
0
        "77e5189111eb6557e8a637b27ef8fbb15bc61d61c2f00cc48878f3a296e5e0ca"
523
0
        "0000000000000000000000000000000000000000000000000000000000000000"
524
0
        "6944c77849b18048f6abe0db8084b0d0d0689cdddb53d2671c36967b58691ad4"
525
0
        "ef4f06ba4f78319baafd0424365777241af4dfd3da840471b4b4b087b7750d0d"
526
0
      ),
527
0
      {
528
0
        fromHex(""),
529
0
        gas_cost
530
0
      }
531
0
    }
532
0
  };
533
0
  evmc::Result result = precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */);
534
  // ECRecover will return success with empty response in case of failure
535
0
  if (result.status_code != EVMC_SUCCESS && result.status_code != EVMC_OUT_OF_GAS)
536
0
    return resultWithGas(_message.gas, gas_cost, {});
537
0
  return result;
538
0
}
539
540
evmc::Result EVMHost::precompileSha256(evmc_message const& _message) noexcept
541
837
{
542
  // static data so that we do not need a release routine...
543
837
  bytes static hash;
544
837
  hash = picosha2::hash256(bytes(
545
837
    _message.input_data,
546
837
    _message.input_data + _message.input_size
547
837
  ));
548
549
  // Base 60 gas + 12 gas / word.
550
837
  int64_t gas_cost = 60 + 12 * ((static_cast<int64_t>(_message.input_size) + 31) / 32);
551
552
837
  return resultWithGas(_message.gas, gas_cost, hash);
553
837
}
554
555
evmc::Result EVMHost::precompileRipeMD160(evmc_message const& _message) noexcept
556
1.04k
{
557
  // NOTE this is a partial implementation for some inputs.
558
559
  // Base 600 gas + 120 gas / word.
560
1.04k
  constexpr auto calc_cost = [](int64_t size) -> int64_t {
561
10
    return 600 + 120 * ((size + 31) / 32);
562
10
  };
563
564
1.04k
  static std::map<bytes, EVMPrecompileOutput> const inputOutput{
565
1.04k
    {
566
1.04k
      bytes{},
567
1.04k
      {
568
1.04k
        fromHex("0000000000000000000000009c1185a5c5e9fc54612808977ee8f548b2258d31"),
569
1.04k
        calc_cost(0)
570
1.04k
      }
571
1.04k
    },
572
1.04k
    {
573
1.04k
      fromHex("0000000000000000000000000000000000000000000000000000000000000004"),
574
1.04k
      {
575
1.04k
        fromHex("0000000000000000000000001b0f3c404d12075c68c938f9f60ebea4f74941a0"),
576
1.04k
        calc_cost(32)
577
1.04k
      }
578
1.04k
    },
579
1.04k
    {
580
1.04k
      fromHex("0000000000000000000000000000000000000000000000000000000000000005"),
581
1.04k
      {
582
1.04k
        fromHex("000000000000000000000000ee54aa84fc32d8fed5a5fe160442ae84626829d9"),
583
1.04k
        calc_cost(32)
584
1.04k
      }
585
1.04k
    },
586
1.04k
    {
587
1.04k
      fromHex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
588
1.04k
      {
589
1.04k
        fromHex("0000000000000000000000001cf4e77f5966e13e109703cd8a0df7ceda7f3dc3"),
590
1.04k
        calc_cost(32)
591
1.04k
      }
592
1.04k
    },
593
1.04k
    {
594
1.04k
      fromHex("0000000000000000000000000000000000000000000000000000000000000000"),
595
1.04k
      {
596
1.04k
        fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc"),
597
1.04k
        calc_cost(32)
598
1.04k
      }
599
1.04k
    },
600
1.04k
    {
601
1.04k
      fromHex(
602
1.04k
        "0800000000000000000000000000000000000000000000000000000000000000"
603
1.04k
        "0401000000000000000000000000000000000000000000000000000000000000"
604
1.04k
        "0000000400000000000000000000000000000000000000000000000000000000"
605
1.04k
        "00000100"
606
1.04k
      ),
607
1.04k
      {
608
1.04k
        fromHex("000000000000000000000000f93175303eba2a7b372174fc9330237f5ad202fc"),
609
1.04k
        calc_cost(100)
610
1.04k
      }
611
1.04k
    },
612
1.04k
    {
613
1.04k
      fromHex(
614
1.04k
        "0800000000000000000000000000000000000000000000000000000000000000"
615
1.04k
        "0501000000000000000000000000000000000000000000000000000000000000"
616
1.04k
        "0000000500000000000000000000000000000000000000000000000000000000"
617
1.04k
        "00000100"
618
1.04k
      ),
619
1.04k
      {
620
1.04k
        fromHex("0000000000000000000000004f4fc112e2bfbe0d38f896a46629e08e2fcfad5"),
621
1.04k
        calc_cost(100)
622
1.04k
      }
623
1.04k
    },
624
1.04k
    {
625
1.04k
      fromHex(
626
1.04k
        "08ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
627
1.04k
        "ff010000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
628
1.04k
        "ffffffff00000000000000000000000000000000000000000000000000000000"
629
1.04k
        "00000100"
630
1.04k
      ),
631
1.04k
      {
632
1.04k
        fromHex("000000000000000000000000c0a2e4b1f3ff766a9a0089e7a410391730872495"),
633
1.04k
        calc_cost(100)
634
1.04k
      }
635
1.04k
    },
636
1.04k
    {
637
1.04k
      fromHex(
638
1.04k
        "6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546"
639
1.04k
        "4748494a4b4c4d4e4f505152535455565758595a303132333435363738393f21"
640
1.04k
      ),
641
1.04k
      {
642
1.04k
        fromHex("00000000000000000000000036c6b90a49e17d4c1e1b0e634ec74124d9b207da"),
643
1.04k
        calc_cost(64)
644
1.04k
      }
645
1.04k
    },
646
1.04k
    {
647
1.04k
      fromHex("6162636465666768696a6b6c6d6e6f707172737475767778797a414243444546"),
648
1.04k
      {
649
1.04k
        fromHex("000000000000000000000000ac5ab22e07b0fb80c69b6207902f725e2507e546"),
650
1.04k
        calc_cost(32)
651
1.04k
      }
652
1.04k
    }
653
1.04k
  };
654
1.04k
  return precompileGeneric(_message, inputOutput);
655
1.04k
}
656
657
evmc::Result EVMHost::precompileIdentity(evmc_message const& _message) noexcept
658
935
{
659
  // static data so that we do not need a release routine...
660
935
  bytes static data;
661
935
  data = bytes(_message.input_data, _message.input_data + _message.input_size);
662
663
  // Base 15 gas + 3 gas / word.
664
935
  int64_t gas_cost = 15 + 3 * ((static_cast<int64_t>(_message.input_size) + 31) / 32);
665
666
935
  return resultWithGas(_message.gas, gas_cost, data);
667
935
}
668
669
evmc::Result EVMHost::precompileModExp(evmc_message const&) noexcept
670
263
{
671
  // TODO implement
672
263
  return resultWithFailure();
673
263
}
674
675
template <evmc_revision Revision>
676
evmc::Result EVMHost::precompileALTBN128G1Add(evmc_message const& _message) noexcept
677
0
{
678
  // NOTE this is a partial implementation for some inputs.
679
680
  // Fixed 500 or 150 gas.
681
0
  int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 500 : 150;
682
683
0
  static std::map<bytes, EVMPrecompileOutput> const inputOutput{
684
0
    {
685
0
      fromHex(
686
0
        "0000000000000000000000000000000000000000000000000000000000000000"
687
0
        "0000000000000000000000000000000000000000000000000000000000000000"
688
0
        "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
689
0
        "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
690
0
      ),
691
0
      {
692
0
        fromHex(
693
0
          "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
694
0
          "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
695
0
        ),
696
0
        gas_cost
697
0
      }
698
0
    },
699
0
    {
700
0
      fromHex(
701
0
        "0000000000000000000000000000000000000000000000000000000000000001"
702
0
        "0000000000000000000000000000000000000000000000000000000000000002"
703
0
        "0000000000000000000000000000000000000000000000000000000000000001"
704
0
        "0000000000000000000000000000000000000000000000000000000000000002"
705
0
      ),
706
0
      {
707
0
        fromHex(
708
0
          "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3"
709
0
          "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"
710
0
        ),
711
0
        gas_cost
712
0
      }
713
0
    },
714
0
    {
715
0
      fromHex(
716
0
        "0000000000000000000000000000000000000000000000000000000000000001"
717
0
        "0000000000000000000000000000000000000000000000000000000000000002"
718
0
        "0000000000000000000000000000000000000000000000000000000000000001"
719
0
        "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"
720
0
      ),
721
0
      {
722
0
        fromHex(
723
0
          "0000000000000000000000000000000000000000000000000000000000000000"
724
0
          "0000000000000000000000000000000000000000000000000000000000000000"
725
0
        ),
726
0
        gas_cost
727
0
      }
728
0
    },
729
0
    {
730
0
      fromHex(
731
0
        "10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8"
732
0
        "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368"
733
0
        "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283"
734
0
        "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"
735
0
      ),
736
0
      {
737
0
        fromHex(
738
0
          "16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94"
739
0
          "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375"
740
0
        ),
741
0
        gas_cost
742
0
      }
743
0
    },
744
0
    {
745
0
      fromHex(
746
0
        "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
747
0
        "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
748
0
        "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf"
749
0
        "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"
750
0
      ),
751
0
      {
752
0
        fromHex(
753
0
          "1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa"
754
0
          "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9"
755
0
        ),
756
0
        gas_cost
757
0
      }
758
0
    },
759
0
    {
760
0
      fromHex(
761
0
        "16aed5ed486df6b2fb38015ded41400009ed4f34bef65b87b1f90f47052f8d94"
762
0
        "16dabf21b3f25b9665269d98dc17b1da6118251dc0b403ae50e96dfe91239375"
763
0
        "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005"
764
0
        "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"
765
0
      ),
766
0
      {
767
0
        fromHex(
768
0
          "29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797"
769
0
          "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a"
770
0
        ),
771
0
        gas_cost
772
0
      }
773
0
    },
774
0
    {
775
0
      fromHex(
776
0
        "18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c"
777
0
        "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd"
778
0
        "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc"
779
0
        "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"
780
0
      ),
781
0
      {
782
0
        fromHex(
783
0
          "2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4"
784
0
          "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7"
785
0
        ),
786
0
        gas_cost
787
0
      }
788
0
    },
789
0
    {
790
0
      fromHex(
791
0
        "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59"
792
0
        "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41"
793
0
        "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
794
0
        "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"
795
0
      ),
796
0
      {
797
0
        fromHex(
798
0
          "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254"
799
0
          "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f"
800
0
        ),
801
0
        gas_cost
802
0
      }
803
0
    },
804
0
    {
805
0
      fromHex(
806
0
        "1e018816fc9bbd91313301ae9c254bb7d64d6cd54f3b49b92925e43e256b5faa"
807
0
        "1d1f2259c715327bedb42c095af6c0267e4e1be836b4e04b3f0502552f93cca9"
808
0
        "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b"
809
0
        "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"
810
0
      ),
811
0
      {
812
0
        fromHex(
813
0
          "2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517"
814
0
          "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4"
815
0
        ),
816
0
        gas_cost
817
0
      }
818
0
    },
819
0
    {
820
0
      fromHex(
821
0
        "2583ed10e418133e44619c336f1be5ddae9e20d634a7683d9661401c750d7df4"
822
0
        "0185fbba22de9e698262925665735dbc4d6e8288bc3fc39fae10ca58e16e77f7"
823
0
        "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6"
824
0
        "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"
825
0
      ),
826
0
      {
827
0
        fromHex(
828
0
          "10b4876441e14a6be92a7fe66550848c01c676a12ac31d7cc13b21f49c4307c8"
829
0
          "09f5528bdb0ef9354837a0f4b4c9da973bd5b805d359976f719ab0b74e0a7368"
830
0
        ),
831
0
        gas_cost
832
0
      }
833
0
    },
834
0
    {
835
0
      fromHex(
836
0
        "26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
837
0
        "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
838
0
        "1496064626ba8bffeb7805f0d16143a65649bb0850333ea512c03fcdaf31e254"
839
0
        "07b4f210ab542533f1ee5633ae4406cd16c63494b537ce3f1cf4afff6f76a48f"
840
0
      ),
841
0
      {
842
0
        fromHex(
843
0
          "186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008"
844
0
          "1e396bc242de0214898b0f68035f53ad5a6f96c6c8390ac56ed6ec9561d23159"
845
0
        ),
846
0
        gas_cost
847
0
      }
848
0
    },
849
0
    {
850
0
      fromHex(
851
0
        "26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
852
0
        "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
853
0
        "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59"
854
0
        "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41"
855
0
      ),
856
0
      {
857
0
        fromHex(
858
0
          "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a"
859
0
          "29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed3021"
860
0
        ),
861
0
        gas_cost
862
0
      }
863
0
    },
864
0
    {
865
0
      fromHex(
866
0
        "27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4"
867
0
        "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1"
868
0
        "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707"
869
0
        "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"
870
0
      ),
871
0
      {
872
0
        fromHex(
873
0
          "18014701594179c6b9ccae848e3d15c1f76f8a68b8092578296520e46c9bae0c"
874
0
          "1b5ed0e9e8f3ff35589ea81a45cf63887d4a92c099a3be1d97b26f0db96323dd"
875
0
        ),
876
0
        gas_cost
877
0
      }
878
0
    },
879
0
    {
880
0
      fromHex(
881
0
        "2801b21090cbc48409e352647f3857134d373f81741f9d5e3d432f336d76f517"
882
0
        "13cf106acf943c2a331de21c7d5e3351354e7412f2dba2918483a6593a6828d4"
883
0
        "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d"
884
0
        "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"
885
0
      ),
886
0
      {
887
0
        fromHex(
888
0
          "27231d5cdd0011259ff75678cf5a8f7840c22cb71d52b25e21e071205e8d9bc4"
889
0
          "26dd3d225c9a71476db0cf834232eba84020f3073c6d20c519963e0b98f235e1"
890
0
        ),
891
0
        gas_cost
892
0
      }
893
0
    },
894
0
    {
895
0
      fromHex(
896
0
        "29d160febeef9770d47a32ee3b763850eb0594844fa57dd31b8ed02c78fdb797"
897
0
        "2c7cdf62c2498486fd52646e577a06723ce97737b3c958262d78c4a413661e8a"
898
0
        "0aee46a7ea6e80a3675026dfa84019deee2a2dedb1bbe11d7fe124cb3efb4b5a"
899
0
        "044747b6e9176e13ede3a4dfd0d33ccca6321b9acd23bf3683a60adc0366ebaf"
900
0
      ),
901
0
      {
902
0
        fromHex(
903
0
          "26dcfbc2e0bc9d82efb4acd73cb3e99730e27e10177fcfb78b6399a4bfcdf391"
904
0
          "27c440dbd5053253a3a692f9bf89b9b6e9612127cf97db1e11ffa9679acc933b"
905
0
        ),
906
0
        gas_cost
907
0
      }
908
0
    }
909
0
  };
910
0
  return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */);
911
0
}
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128G1Add<(evmc_revision)7>(evmc_message const&)
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128G1Add<(evmc_revision)9>(evmc_message const&)
912
913
template <evmc_revision Revision>
914
evmc::Result EVMHost::precompileALTBN128G1Mul(evmc_message const& _message) noexcept
915
0
{
916
  // NOTE this is a partial implementation for some inputs.
917
918
  // Fixed 40000 or 6000 gas.
919
0
  int64_t gas_cost = (Revision < EVMC_ISTANBUL) ? 40000 : 6000;
920
921
0
  static std::map<bytes, EVMPrecompileOutput> const inputOutput{
922
0
    {
923
0
      fromHex(
924
0
        "0000000000000000000000000000000000000000000000000000000000000001"
925
0
        "0000000000000000000000000000000000000000000000000000000000000002"
926
0
        "0000000000000000000000000000000000000000000000000000000000000002"
927
0
      ),
928
0
      {
929
0
        fromHex(
930
0
          "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd3"
931
0
          "15ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4"
932
0
        ),
933
0
        gas_cost
934
0
      }
935
0
    },
936
0
    {
937
0
      fromHex(
938
0
        "0000000000000000000000000000000000000000000000000000000000000001"
939
0
        "0000000000000000000000000000000000000000000000000000000000000002"
940
0
        "0000000000000000000000000000000000000000000000000000000000000005"
941
0
      ),
942
0
      {
943
0
        fromHex(
944
0
          "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9"
945
0
          "01e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c"
946
0
        ),
947
0
        gas_cost
948
0
      }
949
0
    },
950
0
    {
951
0
      fromHex(
952
0
        "09b54f111d3b2d1b2fe1ae9669b3db3d7bf93b70f00647e65c849275de6dc7fe"
953
0
        "18b2e77c63a3e400d6d1f1fbc6e1a1167bbca603d34d03edea231eb0ab7b14b4"
954
0
        "030f7b0c405c888aff922307ea2cd1c70f64664bab76899500341f4260a20929"
955
0
      ),
956
0
      {
957
0
        fromHex(
958
0
          "16a1d378d1a98cf5383cdc512011234287ca43b6a078d1842d5c58c5b1f475cc"
959
0
          "1309377a7026d08ca1529eab74381a7e0d3a4b79d80bacec207cd52fc8e3769c"
960
0
        ),
961
0
        gas_cost
962
0
      }
963
0
    },
964
0
    {
965
0
      fromHex(
966
0
        "0a6de0e2240aa253f46ce0da883b61976e3588146e01c9d8976548c145fe6e4a"
967
0
        "04fbaa3a4aed4bb77f30ebb07a3ec1c7d77a7f2edd75636babfeff97b1ea686e"
968
0
        "1551dcd4965285ef049512d2d30cbfc1a91acd5baad4a6e19e22e93176197f17"
969
0
      ),
970
0
      {
971
0
        fromHex(
972
0
          "28d3c57516712e7843a5b3cfa7d7274a037943f5bd57c227620ad207728e4283"
973
0
          "2795fa9df21d4b8b329a45bae120f1fd9df9049ecacaa9dd1eca18bc6a55cd2f"
974
0
        ),
975
0
        gas_cost
976
0
      }
977
0
    },
978
0
    {
979
0
      fromHex(
980
0
        "0c54b42137b67cc268cbb53ac62b00ecead23984092b494a88befe58445a244a"
981
0
        "18e3723d37fae9262d58b548a0575f59d9c3266db7afb4d5739555837f6b8b3e"
982
0
        "0c692b41f1acc961f6ea83bae2c3a1a55c54f766c63ba76989f52c149c17b5e7"
983
0
      ),
984
0
      {
985
0
        fromHex(
986
0
          "258f1faa356e470cca19c928afa5ceed6215c756912af5725b8db5777cc8f3b6"
987
0
          "175ced8a58d0c132c2b95ba14c16dde93e7f7789214116ff69da6f44daa966e6"
988
0
        ),
989
0
        gas_cost
990
0
      }
991
0
    },
992
0
    {
993
0
      fromHex(
994
0
        "0f103f14a584d4203c27c26155b2c955f8dfa816980b24ba824e1972d6486a5d"
995
0
        "0c4165133b9f5be17c804203af781bcf168da7386620479f9b885ecbcd27b17b"
996
0
        "0ea71d0abb524cac7cfff5323e1d0b14ab705842426c978f96753ccce258ed93"
997
0
      ),
998
0
      {
999
0
        fromHex(
1000
0
          "2a49621e12910cd90f3e731083d454255bf1c533d6e15b8699156778d0f27f5d"
1001
0
          "2590ee31824548d159aa2d22296bf149d564c0872f41b89b7dc5c6e6e3cd1c4d"
1002
0
        ),
1003
0
        gas_cost
1004
0
      }
1005
0
    },
1006
0
    {
1007
0
      fromHex(
1008
0
        "111e2e2a5f8828f80ddad08f9f74db56dac1cc16c1cb278036f79a84cf7a116f"
1009
0
        "1d7d62e192b219b9808faa906c5ced871788f6339e8d91b83ac1343e20a16b30"
1010
0
        "00000000000000000000000000000000000000e40800000000000000008cdcbc"
1011
0
      ),
1012
0
      {
1013
0
        fromHex(
1014
0
          "25ff95a3abccf32adc6a4c3c8caddca67723d8ada802e9b9f612e3ddb40b2005"
1015
0
          "0d82b09bb4ec927bbf182bdc402790429322b7e2f285f2aad8ea135cbf7143d8"
1016
0
        ),
1017
0
        gas_cost
1018
0
      }
1019
0
    },
1020
0
    {
1021
0
      fromHex(
1022
0
        "17d5d09b4146424bff7e6fb01487c477bbfcd0cdbbc92d5d6457aae0b6717cc5"
1023
0
        "02b5636903efbf46db9235bbe74045d21c138897fda32e079040db1a16c1a7a1"
1024
0
        "1887420878c0c8e37605291c626585eabbec8d8b97a848fe8d58a37b00458351"
1025
0
      ),
1026
0
      {
1027
0
        fromHex(
1028
0
          "2364294faf6b89fedeede9986aa777c4f6c2f5c4a4559ee93dfec9b7b94ef80b"
1029
0
          "05aeae62655ea23865ae6661ae371a55c12098703d0f2301f4223e708c92efc6"
1030
0
        ),
1031
0
        gas_cost
1032
0
      }
1033
0
    },
1034
0
    {
1035
0
      fromHex(
1036
0
        "1c36e713d4d54e3a9644dffca1fc524be4868f66572516025a61ca542539d43f"
1037
0
        "042dcc4525b82dfb242b09cb21909d5c22643dcdbe98c4d082cc2877e96b24db"
1038
0
        "016086cc934d5cab679c6991a4efcedbab26d7e4fb23b6a1ad4e6b5c2fb59ce5"
1039
0
      ),
1040
0
      {
1041
0
        fromHex(
1042
0
          "1644e84fef7b7fdc98254f0654580173307a3bc44db990581e7ab55a22446dcf"
1043
0
          "28c2916b7e875692b195831945805438fcd30d2693d8a80cf8c88ec6ef4c315d"
1044
0
        ),
1045
0
        gas_cost
1046
0
      }
1047
0
    },
1048
0
    {
1049
0
      fromHex(
1050
0
        "1e39e9f0f91fa7ff8047ffd90de08785777fe61c0e3434e728fce4cf35047ddc"
1051
0
        "2e0b64d75ebfa86d7f8f8e08abbe2e7ae6e0a1c0b34d028f19fa56e9450527cb"
1052
0
        "1eec35a0e955cad4bee5846ae0f1d0b742d8636b278450c534e38e06a60509f9"
1053
0
      ),
1054
0
      {
1055
0
        fromHex(
1056
0
          "1385281136ff5b2c326807ff0a824b6ca4f21fcc7c8764e9801bc4ad497d5012"
1057
0
          "02254594be8473dcf018a2aa66ea301e38fc865823acf75a9901721d1fc6bf4c"
1058
0
        ),
1059
0
        gas_cost
1060
0
      }
1061
0
    },
1062
0
    {
1063
0
      fromHex(
1064
0
        "232063b584fb76c8d07995bee3a38fa7565405f3549c6a918ddaa90ab971e7f8"
1065
0
        "2ac9b135a81d96425c92d02296322ad56ffb16299633233e4880f95aafa7fda7"
1066
0
        "0689c3dc4311426ee11707866b2cbdf9751dacd07245bf99d2113d3f5a8cac47"
1067
0
      ),
1068
0
      {
1069
0
        fromHex(
1070
0
          "2174f0221490cd9c15b0387f3251ec3d49517a51c37a8076eac12afb4a95a707"
1071
0
          "1d1c3fcd3161e2a417b4df0955f02db1fffa9005210fb30c5aa3755307e9d1f5"
1072
0
        ),
1073
0
        gas_cost
1074
0
      }
1075
0
    }
1076
0
  };
1077
0
  return precompileGeneric(_message, inputOutput, true /* _ignoresTrailingInput */);
1078
0
}
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128G1Mul<(evmc_revision)7>(evmc_message const&)
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128G1Mul<(evmc_revision)9>(evmc_message const&)
1079
1080
template <evmc_revision Revision>
1081
evmc::Result EVMHost::precompileALTBN128PairingProduct(evmc_message const& _message) noexcept
1082
0
{
1083
  // Base + per pairing gas.
1084
0
  constexpr auto calc_cost = [](unsigned points) -> int64_t {
1085
    // Number of 192-byte points.
1086
0
    return (Revision < EVMC_ISTANBUL) ?
1087
0
      (100000 + 80000 * points):
1088
0
      (45000 + 34000 * points);
1089
0
  };
Unexecuted instantiation: solidity::test::EVMHost::precompileALTBN128PairingProduct<(evmc_revision)7>(evmc_message const&)::{lambda(unsigned int)#1}::operator()(unsigned int) const
Unexecuted instantiation: solidity::test::EVMHost::precompileALTBN128PairingProduct<(evmc_revision)9>(evmc_message const&)::{lambda(unsigned int)#1}::operator()(unsigned int) const
1090
1091
  // NOTE this is a partial implementation for some inputs.
1092
0
  static std::map<bytes, EVMPrecompileOutput> const inputOutput{
1093
0
    {
1094
0
      fromHex(
1095
0
        "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa9"
1096
0
        "01e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c"
1097
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1098
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1099
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1100
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1101
0
        "0000000000000000000000000000000000000000000000000000000000000001"
1102
0
        "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"
1103
0
        "0a09ccf561b55fd99d1c1208dee1162457b57ac5af3759d50671e510e428b2a1"
1104
0
        "2e539c423b302d13f4e5773c603948eaf5db5df8ae8a9a9113708390a06410d8"
1105
0
        "19b763513924a736e4eebd0d78c91c1bc1d657fee4214057d21414011cfcc763"
1106
0
        "2f8d9f9ab83727c77a2fec063cb7b6e5eb23044ccf535ad49d46d394fb6f6bf6"
1107
0
      ),
1108
0
      {
1109
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1110
0
        calc_cost(2)
1111
0
      }
1112
0
    },
1113
0
    {
1114
0
      fromHex(
1115
0
        "0000000000000000000000000000000000000000000000000000000000000001"
1116
0
        "0000000000000000000000000000000000000000000000000000000000000002"
1117
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1118
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1119
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1120
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1121
0
        "0000000000000000000000000000000000000000000000000000000000000001"
1122
0
        "30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd45"
1123
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1124
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1125
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1126
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1127
0
      ),
1128
0
      {
1129
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1130
0
        calc_cost(2)
1131
0
      }
1132
0
    },
1133
0
    {
1134
0
      fromHex(
1135
0
        "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59"
1136
0
        "3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41"
1137
0
        "209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7"
1138
0
        "04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678"
1139
0
        "2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d"
1140
0
        "120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550"
1141
0
        "111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c"
1142
0
        "2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411"
1143
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1144
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1145
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1146
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1147
0
      ),
1148
0
      {
1149
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1150
0
        calc_cost(2)
1151
0
      }
1152
0
    },
1153
0
    {
1154
0
      fromHex(
1155
0
        "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc02"
1156
0
        "03d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db84"
1157
0
        "1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee"
1158
0
        "2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f"
1159
0
        "21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237"
1160
0
        "096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f"
1161
0
        "06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db9"
1162
0
        "22160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1"
1163
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1164
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1165
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1166
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1167
0
      ),
1168
0
      {
1169
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1170
0
        calc_cost(2)
1171
0
      }
1172
0
    },
1173
0
    {
1174
0
      fromHex(
1175
0
        "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
1176
0
        "16da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba"
1177
0
        "2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb"
1178
0
        "01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb3"
1179
0
        "14a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713"
1180
0
        "178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee24590"
1181
0
        "1b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b8"
1182
0
        "11d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21"
1183
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1184
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1185
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1186
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1187
0
      ),
1188
0
      {
1189
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1190
0
        calc_cost(2)
1191
0
      }
1192
0
    },
1193
0
    {
1194
0
      fromHex(
1195
0
        "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6"
1196
0
        "068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b72"
1197
0
        "25f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb1"
1198
0
        "22acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d"
1199
0
        "065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf68"
1200
0
        "06d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb"
1201
0
        "186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008"
1202
0
        "122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee"
1203
0
        "1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e"
1204
0
        "283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39"
1205
0
        "140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e"
1206
0
        "0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd4"
1207
0
        "15794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f21"
1208
0
        "1b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da"
1209
0
        "1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee"
1210
0
        "2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f"
1211
0
        "21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237"
1212
0
        "096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f"
1213
0
      ),
1214
0
      {
1215
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1216
0
        calc_cost(3)
1217
0
      }
1218
0
    },
1219
0
    {
1220
0
      fromHex(
1221
0
        "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a"
1222
0
        "29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed3021"
1223
0
        "1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee"
1224
0
        "2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f"
1225
0
        "21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237"
1226
0
        "096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f"
1227
0
        "1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c1"
1228
0
        "1073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869"
1229
0
        "217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac29"
1230
0
        "0a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c"
1231
0
        "26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a9855"
1232
0
        "2fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d7"
1233
0
        "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2"
1234
0
        "198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d"
1235
0
        "198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2"
1236
0
        "1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed"
1237
0
        "090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b"
1238
0
        "12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa"
1239
0
      ),
1240
0
      {
1241
0
        fromHex("0000000000000000000000000000000000000000000000000000000000000001"),
1242
0
        calc_cost(3)
1243
0
      }
1244
0
    }
1245
0
  };
1246
1247
0
  return precompileGeneric(_message, inputOutput);
1248
0
}
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128PairingProduct<(evmc_revision)7>(evmc_message const&)
Unexecuted instantiation: evmc::Result solidity::test::EVMHost::precompileALTBN128PairingProduct<(evmc_revision)9>(evmc_message const&)
1249
1250
evmc::Result EVMHost::precompileBlake2f(evmc_message const&) noexcept
1251
20
{
1252
  // TODO implement
1253
20
  return resultWithFailure();
1254
20
}
1255
1256
evmc::Result EVMHost::precompileGeneric(
1257
  evmc_message const& _message,
1258
  std::map<bytes, EVMPrecompileOutput> const& _inOut,
1259
  bool _ignoresTrailingInput
1260
) noexcept
1261
1.04k
{
1262
1.04k
  size_t meaningfulInputSize = _message.input_size;
1263
1.04k
  if (_ignoresTrailingInput && !_inOut.empty())
1264
0
  {
1265
    // _ignoresTrailingInput only implemented for the case where all inputs have same size.
1266
    // Simpler to implement and it's all we need for now.
1267
0
    for (auto const& [input, output]: _inOut)
1268
0
      solAssert(input.size() == _inOut.begin()->first.size());
1269
1270
    // If there is more input that expected, precompiles tend to simply ignore it.
1271
0
    meaningfulInputSize = std::min(_message.input_size, _inOut.begin()->first.size());
1272
0
  }
1273
1274
1.04k
  bytes input(_message.input_data, _message.input_data + meaningfulInputSize);
1275
1.04k
  if (_inOut.count(input))
1276
1.04k
  {
1277
1.04k
    auto const& ret = _inOut.at(input);
1278
1.04k
    return resultWithGas(_message.gas, ret.gas_used, ret.output);
1279
1.04k
  }
1280
0
  else
1281
    // FIXME: We're in a noexcept function; this will result in terminate() and then abort().
1282
    // Still better than nothing - can't be mistaken for revert and Boost will report test name.
1283
0
    solThrow(
1284
1.04k
      Exception,
1285
1.04k
      "Test output for a precompile not defined for input: " + toHex(input, HexPrefix::Add)
1286
1.04k
    );
1287
1.04k
}
1288
1289
evmc::Result EVMHost::resultWithFailure() noexcept
1290
283
{
1291
283
  evmc::Result result;
1292
283
  result.status_code = EVMC_FAILURE;
1293
283
  return result;
1294
283
}
1295
1296
evmc::Result EVMHost::resultWithGas(
1297
  int64_t gas_limit,
1298
  int64_t gas_required,
1299
  bytes const& _data
1300
) noexcept
1301
2.81k
{
1302
2.81k
  evmc::Result result;
1303
2.81k
  if (gas_limit < gas_required)
1304
1.11k
  {
1305
1.11k
    result.status_code = EVMC_OUT_OF_GAS;
1306
1.11k
    result.gas_left = 0;
1307
1.11k
  }
1308
1.70k
  else
1309
1.70k
  {
1310
1.70k
    result.status_code = EVMC_SUCCESS;
1311
1.70k
    result.gas_left = gas_limit - gas_required;
1312
1.70k
  }
1313
2.81k
  result.output_data = _data.empty() ? nullptr : _data.data();
1314
2.81k
  result.output_size = _data.size();
1315
2.81k
  return result;
1316
2.81k
}
1317
1318
StorageMap const& EVMHost::get_address_storage(evmc::address const& _addr)
1319
22.0k
{
1320
22.0k
  soltestAssert(account_exists(_addr), "Account does not exist.");
1321
22.0k
  return accounts[_addr].storage;
1322
22.0k
}
1323
1324
std::string EVMHostPrinter::state()
1325
22.0k
{
1326
  // Print state and execution trace.
1327
22.0k
  if (m_host.account_exists(m_account))
1328
22.0k
  {
1329
22.0k
    storage();
1330
22.0k
    balance();
1331
22.0k
  }
1332
0
  else
1333
0
    selfdestructRecords();
1334
1335
22.0k
  callRecords();
1336
22.0k
  return m_stateStream.str();
1337
22.0k
}
1338
1339
void EVMHostPrinter::storage()
1340
22.0k
{
1341
22.0k
  for (auto const& [slot, value]: m_host.get_address_storage(m_account))
1342
97.7k
    if (m_host.get_storage(m_account, slot))
1343
44.9k
      m_stateStream << "  "
1344
44.9k
        << m_host.convertFromEVMC(slot)
1345
44.9k
        << ": "
1346
44.9k
        << m_host.convertFromEVMC(value.current)
1347
44.9k
        << std::endl;
1348
22.0k
}
1349
1350
void EVMHostPrinter::balance()
1351
22.0k
{
1352
22.0k
  m_stateStream << "BALANCE "
1353
22.0k
    << m_host.convertFromEVMC(m_host.get_balance(m_account))
1354
22.0k
    << std::endl;
1355
22.0k
}
1356
1357
void EVMHostPrinter::selfdestructRecords()
1358
0
{
1359
0
  for (auto const& record: m_host.recorded_selfdestructs)
1360
0
    for (auto const& beneficiary: record.second)
1361
0
      m_stateStream << "SELFDESTRUCT"
1362
0
        << " BENEFICIARY "
1363
0
        << m_host.convertFromEVMC(beneficiary)
1364
0
        << std::endl;
1365
0
}
1366
1367
void EVMHostPrinter::callRecords()
1368
22.0k
{
1369
22.0k
  static auto constexpr callKind = [](evmc_call_kind _kind) -> std::string
1370
71.1k
  {
1371
71.1k
    switch (_kind)
1372
71.1k
    {
1373
26.2k
      case evmc_call_kind::EVMC_CALL:
1374
26.2k
        return "CALL";
1375
22.7k
      case evmc_call_kind::EVMC_DELEGATECALL:
1376
22.7k
        return "DELEGATECALL";
1377
188
      case evmc_call_kind::EVMC_CALLCODE:
1378
188
        return "CALLCODE";
1379
22.0k
      case evmc_call_kind::EVMC_CREATE:
1380
22.0k
        return "CREATE";
1381
0
      case evmc_call_kind::EVMC_CREATE2:
1382
0
        return "CREATE2";
1383
71.1k
    }
1384
0
    unreachable();
1385
0
  };
1386
1387
22.0k
  for (auto const& record: m_host.recorded_calls)
1388
71.1k
    m_stateStream << callKind(record.kind)
1389
71.1k
      << " VALUE "
1390
71.1k
      << m_host.convertFromEVMC(record.value)
1391
71.1k
      << std::endl;
1392
22.0k
}