Coverage Report

Created: 2022-08-24 06:55

/src/solidity/test/tools/yulInterpreter/EVMInstructionInterpreter.cpp
Line
Count
Source (jump to first uncovered line)
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
 * Yul interpreter module that evaluates EVM instructions.
20
 */
21
22
#include <test/tools/yulInterpreter/EVMInstructionInterpreter.h>
23
24
#include <test/tools/yulInterpreter/Interpreter.h>
25
26
#include <libyul/backends/evm/EVMDialect.h>
27
#include <libyul/AST.h>
28
29
#include <libevmasm/Instruction.h>
30
#include <libevmasm/SemanticInformation.h>
31
32
#include <libsolutil/Keccak256.h>
33
#include <libsolutil/Numeric.h>
34
35
#include <limits>
36
37
using namespace std;
38
using namespace solidity;
39
using namespace solidity::evmasm;
40
using namespace solidity::yul;
41
using namespace solidity::yul::test;
42
43
using solidity::util::h160;
44
using solidity::util::h256;
45
using solidity::util::keccak256;
46
47
namespace
48
{
49
50
/// Reads 32 bytes from @a _data at position @a _offset bytes while
51
/// interpreting @a _data to be padded with an infinite number of zero
52
/// bytes beyond its end.
53
u256 readZeroExtended(bytes const& _data, u256 const& _offset)
54
26.2k
{
55
26.2k
  if (_offset >= _data.size())
56
17.7k
    return 0;
57
8.45k
  else if (_offset + 32 <= _data.size())
58
7.99k
    return *reinterpret_cast<h256 const*>(_data.data() + static_cast<size_t>(_offset));
59
458
  else
60
458
  {
61
458
    size_t off = static_cast<size_t>(_offset);
62
458
    u256 val;
63
15.1k
    for (size_t i = 0; i < 32; ++i)
64
14.6k
    {
65
14.6k
      val <<= 8;
66
14.6k
      if (off + i < _data.size())
67
2.69k
        val += _data[off + i];
68
14.6k
    }
69
458
    return val;
70
458
  }
71
26.2k
}
72
73
/// Copy @a _size bytes of @a _source at offset @a _sourceOffset to
74
/// @a _target at offset @a _targetOffset. Behaves as if @a _source would
75
/// continue with an infinite sequence of zero bytes beyond its end.
76
void copyZeroExtended(
77
  map<u256, uint8_t>& _target, bytes const& _source,
78
  size_t _targetOffset, size_t _sourceOffset, size_t _size
79
)
80
7.85k
{
81
24.6M
  for (size_t i = 0; i < _size; ++i)
82
24.6M
    _target[_targetOffset + i] = _sourceOffset + i < _source.size() ? _source[_sourceOffset + i] : 0;
83
7.85k
}
84
85
}
86
87
using u512 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<512, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>;
88
89
u256 EVMInstructionInterpreter::eval(
90
  evmasm::Instruction _instruction,
91
  vector<u256> const& _arguments
92
)
93
1.69M
{
94
1.69M
  using namespace solidity::evmasm;
95
1.69M
  using evmasm::Instruction;
96
97
1.69M
  auto info = instructionInfo(_instruction);
98
1.69M
  yulAssert(static_cast<size_t>(info.args) == _arguments.size(), "");
99
100
1.69M
  auto const& arg = _arguments;
101
1.69M
  switch (_instruction)
102
1.69M
  {
103
642
  case Instruction::STOP:
104
642
    logTrace(_instruction);
105
642
    BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
106
  // --------------- arithmetic ---------------
107
100k
  case Instruction::ADD:
108
100k
    return arg[0] + arg[1];
109
43.5k
  case Instruction::MUL:
110
43.5k
    return arg[0] * arg[1];
111
54.4k
  case Instruction::SUB:
112
54.4k
    return arg[0] - arg[1];
113
87.8k
  case Instruction::DIV:
114
87.8k
    return arg[1] == 0 ? 0 : arg[0] / arg[1];
115
55.1k
  case Instruction::SDIV:
116
55.1k
    return arg[1] == 0 ? 0 : s2u(u2s(arg[0]) / u2s(arg[1]));
117
25.3k
  case Instruction::MOD:
118
25.3k
    return arg[1] == 0 ? 0 : arg[0] % arg[1];
119
23.1k
  case Instruction::SMOD:
120
23.1k
    return arg[1] == 0 ? 0 : s2u(u2s(arg[0]) % u2s(arg[1]));
121
29.8k
  case Instruction::EXP:
122
29.8k
    return exp256(arg[0], arg[1]);
123
139k
  case Instruction::NOT:
124
139k
    return ~arg[0];
125
88.0k
  case Instruction::LT:
126
88.0k
    return arg[0] < arg[1] ? 1 : 0;
127
6.59k
  case Instruction::GT:
128
6.59k
    return arg[0] > arg[1] ? 1 : 0;
129
2.39k
  case Instruction::SLT:
130
2.39k
    return u2s(arg[0]) < u2s(arg[1]) ? 1 : 0;
131
6.09k
  case Instruction::SGT:
132
6.09k
    return u2s(arg[0]) > u2s(arg[1]) ? 1 : 0;
133
5.85k
  case Instruction::EQ:
134
5.85k
    return arg[0] == arg[1] ? 1 : 0;
135
10.6k
  case Instruction::ISZERO:
136
10.6k
    return arg[0] == 0 ? 1 : 0;
137
7.71k
  case Instruction::AND:
138
7.71k
    return arg[0] & arg[1];
139
64.6k
  case Instruction::OR:
140
64.6k
    return arg[0] | arg[1];
141
16.1k
  case Instruction::XOR:
142
16.1k
    return arg[0] ^ arg[1];
143
6.98k
  case Instruction::BYTE:
144
6.98k
    return arg[0] >= 32 ? 0 : (arg[1] >> unsigned(8 * (31 - arg[0]))) & 0xff;
145
72.9k
  case Instruction::SHL:
146
72.9k
    return arg[0] > 255 ? 0 : (arg[1] << unsigned(arg[0]));
147
21.5k
  case Instruction::SHR:
148
21.5k
    return arg[0] > 255 ? 0 : (arg[1] >> unsigned(arg[0]));
149
31.4k
  case Instruction::SAR:
150
31.4k
  {
151
31.4k
    static u256 const hibit = u256(1) << 255;
152
31.4k
    if (arg[0] >= 256)
153
6.84k
      return arg[1] & hibit ? u256(-1) : 0;
154
24.6k
    else
155
24.6k
    {
156
24.6k
      unsigned amount = unsigned(arg[0]);
157
24.6k
      u256 v = arg[1] >> amount;
158
24.6k
      if (arg[1] & hibit)
159
2.73k
        v |= u256(-1) << (256 - amount);
160
24.6k
      return v;
161
24.6k
    }
162
31.4k
  }
163
53.1k
  case Instruction::ADDMOD:
164
53.1k
    return arg[2] == 0 ? 0 : u256((u512(arg[0]) + u512(arg[1])) % arg[2]);
165
43.6k
  case Instruction::MULMOD:
166
43.6k
    return arg[2] == 0 ? 0 : u256((u512(arg[0]) * u512(arg[1])) % arg[2]);
167
13.8k
  case Instruction::SIGNEXTEND:
168
13.8k
    if (arg[0] >= 31)
169
4.98k
      return arg[1];
170
8.90k
    else
171
8.90k
    {
172
8.90k
      unsigned testBit = unsigned(arg[0]) * 8 + 7;
173
8.90k
      u256 ret = arg[1];
174
8.90k
      u256 mask = ((u256(1) << testBit) - 1);
175
8.90k
      if (boost::multiprecision::bit_test(ret, testBit))
176
2.94k
        ret |= ~mask;
177
5.96k
      else
178
5.96k
        ret &= mask;
179
8.90k
      return ret;
180
8.90k
    }
181
  // --------------- blockchain stuff ---------------
182
27.4k
  case Instruction::KECCAK256:
183
27.4k
  {
184
27.4k
    if (!accessMemory(arg[0], arg[1]))
185
18.7k
      return u256("0x1234cafe1234cafe1234cafe") + arg[0];
186
8.66k
    uint64_t offset = uint64_t(arg[0] & uint64_t(-1));
187
8.66k
    uint64_t size = uint64_t(arg[1] & uint64_t(-1));
188
8.66k
    return u256(keccak256(readMemory(offset, size)));
189
27.4k
  }
190
5.75k
  case Instruction::ADDRESS:
191
5.75k
    return h256(m_state.address, h256::AlignRight);
192
3.92k
  case Instruction::BALANCE:
193
3.92k
    if (arg[0] == h256(m_state.address, h256::AlignRight))
194
68
      return m_state.selfbalance;
195
3.85k
    else
196
3.85k
      return m_state.balance;
197
2.02k
  case Instruction::SELFBALANCE:
198
2.02k
    return m_state.selfbalance;
199
10.7k
  case Instruction::ORIGIN:
200
10.7k
    return h256(m_state.origin, h256::AlignRight);
201
3.98k
  case Instruction::CALLER:
202
3.98k
    return h256(m_state.caller, h256::AlignRight);
203
2.04k
  case Instruction::CALLVALUE:
204
2.04k
    return m_state.callvalue;
205
26.2k
  case Instruction::CALLDATALOAD:
206
26.2k
    return readZeroExtended(m_state.calldata, arg[0]);
207
3.81k
  case Instruction::CALLDATASIZE:
208
3.81k
    return m_state.calldata.size();
209
5.74k
  case Instruction::CALLDATACOPY:
210
5.74k
    logTrace(_instruction, arg);
211
5.74k
    if (accessMemory(arg[0], arg[2]))
212
1.09k
      copyZeroExtended(
213
1.09k
        m_state.memory, m_state.calldata,
214
1.09k
        size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
215
1.09k
      );
216
5.74k
    return 0;
217
5.98k
  case Instruction::CODESIZE:
218
5.98k
    return m_state.code.size();
219
7.11k
  case Instruction::CODECOPY:
220
7.11k
    logTrace(_instruction, arg);
221
7.11k
    if (accessMemory(arg[0], arg[2]))
222
1.86k
      copyZeroExtended(
223
1.86k
        m_state.memory, m_state.code,
224
1.86k
        size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
225
1.86k
      );
226
7.11k
    return 0;
227
3.14k
  case Instruction::GASPRICE:
228
3.14k
    return m_state.gasprice;
229
4.74k
  case Instruction::CHAINID:
230
4.74k
    return m_state.chainid;
231
0
  case Instruction::BASEFEE:
232
0
    return m_state.basefee;
233
4.12k
  case Instruction::EXTCODESIZE:
234
4.12k
    return u256(keccak256(h256(arg[0]))) & 0xffffff;
235
5.58k
  case Instruction::EXTCODEHASH:
236
5.58k
    return u256(keccak256(h256(arg[0] + 1)));
237
14.8k
  case Instruction::EXTCODECOPY:
238
14.8k
    logTrace(_instruction, arg);
239
14.8k
    if (accessMemory(arg[1], arg[3]))
240
      // TODO this way extcodecopy and codecopy do the same thing.
241
3.16k
      copyZeroExtended(
242
3.16k
        m_state.memory, m_state.code,
243
3.16k
        size_t(arg[1]), size_t(arg[2]), size_t(arg[3])
244
3.16k
      );
245
14.8k
    return 0;
246
1.92k
  case Instruction::RETURNDATASIZE:
247
1.92k
    return m_state.returndata.size();
248
2.06k
  case Instruction::RETURNDATACOPY:
249
2.06k
    logTrace(_instruction, arg);
250
2.06k
    if (accessMemory(arg[0], arg[2]))
251
619
      copyZeroExtended(
252
619
        m_state.memory, m_state.returndata,
253
619
        size_t(arg[0]), size_t(arg[1]), size_t(arg[2])
254
619
      );
255
2.06k
    return 0;
256
6.25k
  case Instruction::BLOCKHASH:
257
6.25k
    if (arg[0] >= m_state.blockNumber || arg[0] + 256 < m_state.blockNumber)
258
5.72k
      return 0;
259
530
    else
260
530
      return 0xaaaaaaaa + (arg[0] - m_state.blockNumber - 256);
261
5.62k
  case Instruction::COINBASE:
262
5.62k
    return h256(m_state.coinbase, h256::AlignRight);
263
2.39k
  case Instruction::TIMESTAMP:
264
2.39k
    return m_state.timestamp;
265
3.14k
  case Instruction::NUMBER:
266
3.14k
    return m_state.blockNumber;
267
3.62k
  case Instruction::DIFFICULTY:
268
3.62k
    return m_state.difficulty;
269
1.93k
  case Instruction::GASLIMIT:
270
1.93k
    return m_state.gaslimit;
271
  // --------------- memory / storage / logs ---------------
272
78.6k
  case Instruction::MLOAD:
273
78.6k
    accessMemory(arg[0], 0x20);
274
78.6k
    return readMemoryWord(arg[0]);
275
84.4k
  case Instruction::MSTORE:
276
84.4k
    accessMemory(arg[0], 0x20);
277
84.4k
    writeMemoryWord(arg[0], arg[1]);
278
84.4k
    return 0;
279
10.8k
  case Instruction::MSTORE8:
280
10.8k
    accessMemory(arg[0], 1);
281
10.8k
    m_state.memory[arg[0]] = uint8_t(arg[1] & 0xff);
282
10.8k
    return 0;
283
58.3k
  case Instruction::SLOAD:
284
58.3k
    return m_state.storage[h256(arg[0])];
285
107k
  case Instruction::SSTORE:
286
107k
    m_state.storage[h256(arg[0])] = h256(arg[1]);
287
107k
    return 0;
288
0
  case Instruction::PC:
289
0
    return 0x77;
290
39.7k
  case Instruction::MSIZE:
291
39.7k
    return m_state.msize;
292
19.3k
  case Instruction::GAS:
293
19.3k
    return 0x99;
294
4.47k
  case Instruction::LOG0:
295
4.47k
    accessMemory(arg[0], arg[1]);
296
4.47k
    logTrace(_instruction, arg);
297
4.47k
    return 0;
298
5.68k
  case Instruction::LOG1:
299
5.68k
    accessMemory(arg[0], arg[1]);
300
5.68k
    logTrace(_instruction, arg);
301
5.68k
    return 0;
302
1.70k
  case Instruction::LOG2:
303
1.70k
    accessMemory(arg[0], arg[1]);
304
1.70k
    logTrace(_instruction, arg);
305
1.70k
    return 0;
306
855
  case Instruction::LOG3:
307
855
    accessMemory(arg[0], arg[1]);
308
855
    logTrace(_instruction, arg);
309
855
    return 0;
310
1.19k
  case Instruction::LOG4:
311
1.19k
    accessMemory(arg[0], arg[1]);
312
1.19k
    logTrace(_instruction, arg);
313
1.19k
    return 0;
314
  // --------------- calls ---------------
315
27.7k
  case Instruction::CREATE:
316
27.7k
    accessMemory(arg[1], arg[2]);
317
27.7k
    logTrace(_instruction, arg);
318
27.7k
    return (0xcccccc + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
319
5.01k
  case Instruction::CREATE2:
320
5.01k
    accessMemory(arg[2], arg[3]);
321
5.01k
    logTrace(_instruction, arg);
322
5.01k
    return (0xdddddd + arg[1]) & u256("0xffffffffffffffffffffffffffffffffffffffff");
323
47.7k
  case Instruction::CALL:
324
51.0k
  case Instruction::CALLCODE:
325
    // TODO assign returndata
326
51.0k
    accessMemory(arg[3], arg[4]);
327
51.0k
    accessMemory(arg[5], arg[6]);
328
51.0k
    logTrace(_instruction, arg);
329
51.0k
    return arg[0] & 1;
330
2.08k
  case Instruction::DELEGATECALL:
331
4.05k
  case Instruction::STATICCALL:
332
4.05k
    accessMemory(arg[2], arg[3]);
333
4.05k
    accessMemory(arg[4], arg[5]);
334
4.05k
    logTrace(_instruction, arg);
335
4.05k
    return 0;
336
624
  case Instruction::RETURN:
337
624
  {
338
624
    bytes data;
339
624
    if (accessMemory(arg[0], arg[1]))
340
181
      data = readMemory(arg[0], arg[1]);
341
624
    logTrace(_instruction, arg, data);
342
624
    BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
343
2.08k
  }
344
257
  case Instruction::REVERT:
345
257
    accessMemory(arg[0], arg[1]);
346
257
    logTrace(_instruction, arg);
347
257
    m_state.storage.clear();
348
257
    m_state.trace.clear();
349
257
    BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
350
446
  case Instruction::INVALID:
351
446
    logTrace(_instruction);
352
446
    m_state.storage.clear();
353
446
    m_state.trace.clear();
354
446
    BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
355
834
  case Instruction::SELFDESTRUCT:
356
834
    logTrace(_instruction, arg);
357
834
    m_state.storage.clear();
358
834
    m_state.trace.clear();
359
834
    BOOST_THROW_EXCEPTION(ExplicitlyTerminated());
360
14.0k
  case Instruction::POP:
361
14.0k
    break;
362
  // --------------- invalid in strict assembly ---------------
363
0
  case Instruction::JUMP:
364
0
  case Instruction::JUMPI:
365
0
  case Instruction::JUMPDEST:
366
0
  case Instruction::PUSH1:
367
0
  case Instruction::PUSH2:
368
0
  case Instruction::PUSH3:
369
0
  case Instruction::PUSH4:
370
0
  case Instruction::PUSH5:
371
0
  case Instruction::PUSH6:
372
0
  case Instruction::PUSH7:
373
0
  case Instruction::PUSH8:
374
0
  case Instruction::PUSH9:
375
0
  case Instruction::PUSH10:
376
0
  case Instruction::PUSH11:
377
0
  case Instruction::PUSH12:
378
0
  case Instruction::PUSH13:
379
0
  case Instruction::PUSH14:
380
0
  case Instruction::PUSH15:
381
0
  case Instruction::PUSH16:
382
0
  case Instruction::PUSH17:
383
0
  case Instruction::PUSH18:
384
0
  case Instruction::PUSH19:
385
0
  case Instruction::PUSH20:
386
0
  case Instruction::PUSH21:
387
0
  case Instruction::PUSH22:
388
0
  case Instruction::PUSH23:
389
0
  case Instruction::PUSH24:
390
0
  case Instruction::PUSH25:
391
0
  case Instruction::PUSH26:
392
0
  case Instruction::PUSH27:
393
0
  case Instruction::PUSH28:
394
0
  case Instruction::PUSH29:
395
0
  case Instruction::PUSH30:
396
0
  case Instruction::PUSH31:
397
0
  case Instruction::PUSH32:
398
0
  case Instruction::DUP1:
399
0
  case Instruction::DUP2:
400
0
  case Instruction::DUP3:
401
0
  case Instruction::DUP4:
402
0
  case Instruction::DUP5:
403
0
  case Instruction::DUP6:
404
0
  case Instruction::DUP7:
405
0
  case Instruction::DUP8:
406
0
  case Instruction::DUP9:
407
0
  case Instruction::DUP10:
408
0
  case Instruction::DUP11:
409
0
  case Instruction::DUP12:
410
0
  case Instruction::DUP13:
411
0
  case Instruction::DUP14:
412
0
  case Instruction::DUP15:
413
0
  case Instruction::DUP16:
414
0
  case Instruction::SWAP1:
415
0
  case Instruction::SWAP2:
416
0
  case Instruction::SWAP3:
417
0
  case Instruction::SWAP4:
418
0
  case Instruction::SWAP5:
419
0
  case Instruction::SWAP6:
420
0
  case Instruction::SWAP7:
421
0
  case Instruction::SWAP8:
422
0
  case Instruction::SWAP9:
423
0
  case Instruction::SWAP10:
424
0
  case Instruction::SWAP11:
425
0
  case Instruction::SWAP12:
426
0
  case Instruction::SWAP13:
427
0
  case Instruction::SWAP14:
428
0
  case Instruction::SWAP15:
429
0
  case Instruction::SWAP16:
430
0
  {
431
0
    yulAssert(false, "");
432
0
    return 0;
433
0
  }
434
1.69M
  }
435
436
14.0k
  return 0;
437
1.69M
}
438
439
u256 EVMInstructionInterpreter::evalBuiltin(
440
  BuiltinFunctionForEVM const& _fun,
441
  vector<Expression> const& _arguments,
442
  vector<u256> const& _evaluatedArguments
443
)
444
1.70M
{
445
1.70M
  if (_fun.instruction)
446
1.69M
    return eval(*_fun.instruction, _evaluatedArguments);
447
448
15.0k
  string fun = _fun.name.str();
449
  // Evaluate datasize/offset/copy instructions
450
15.0k
  if (fun == "datasize" || fun == "dataoffset")
451
12.7k
  {
452
12.7k
    string arg = std::get<Literal>(_arguments.at(0)).value.str();
453
12.7k
    if (arg.length() < 32)
454
12.5k
      arg.resize(32, 0);
455
12.7k
    if (fun == "datasize")
456
9.12k
      return u256(keccak256(arg)) & 0xfff;
457
3.66k
    else
458
3.66k
    {
459
      // Force different value than for datasize
460
3.66k
      arg[31]++;
461
3.66k
      arg[31]++;
462
3.66k
      return u256(keccak256(arg)) & 0xfff;
463
3.66k
    }
464
12.7k
  }
465
2.27k
  else if (fun == "datacopy")
466
2.27k
  {
467
    // This is identical to codecopy.
468
2.27k
    if (accessMemory(_evaluatedArguments.at(0), _evaluatedArguments.at(2)))
469
1.11k
      copyZeroExtended(
470
1.11k
        m_state.memory,
471
1.11k
        m_state.code,
472
1.11k
        size_t(_evaluatedArguments.at(0)),
473
1.11k
        size_t(_evaluatedArguments.at(1) & numeric_limits<size_t>::max()),
474
1.11k
        size_t(_evaluatedArguments.at(2))
475
1.11k
      );
476
2.27k
    return 0;
477
2.27k
  }
478
0
  else
479
2.27k
    yulAssert(false, "Unknown builtin: " + fun);
480
0
  return 0;
481
15.0k
}
482
483
484
bool EVMInstructionInterpreter::accessMemory(u256 const& _offset, u256 const& _size)
485
391k
{
486
391k
  if (((_offset + _size) >= _offset) && ((_offset + _size + 0x1f) >= (_offset + _size)))
487
382k
  {
488
382k
    u256 newSize = (_offset + _size + 0x1f) & ~u256(0x1f);
489
382k
    m_state.msize = max(m_state.msize, newSize);
490
    // We only record accesses to contiguous memory chunks that are at most 0xffff bytes
491
    // in size and at an offset of at most numeric_limits<size_t>::max() - 0xffff
492
382k
    return _size <= 0xffff && _offset <= u256(numeric_limits<size_t>::max() - 0xffff);
493
382k
  }
494
8.91k
  else
495
8.91k
    m_state.msize = u256(-1);
496
497
8.91k
  return false;
498
391k
}
499
500
bytes EVMInstructionInterpreter::readMemory(u256 const& _offset, u256 const& _size)
501
87.5k
{
502
87.5k
  yulAssert(_size <= 0xffff, "Too large read.");
503
87.5k
  bytes data(size_t(_size), uint8_t(0));
504
12.4M
  for (size_t i = 0; i < data.size(); ++i)
505
12.3M
    data[i] = m_state.memory[_offset + i];
506
87.5k
  return data;
507
87.5k
}
508
509
u256 EVMInstructionInterpreter::readMemoryWord(u256 const& _offset)
510
78.6k
{
511
78.6k
  return u256(h256(readMemory(_offset, 32)));
512
78.6k
}
513
514
void EVMInstructionInterpreter::writeMemoryWord(u256 const& _offset, u256 const& _value)
515
84.4k
{
516
2.78M
  for (size_t i = 0; i < 32; i++)
517
2.70M
    m_state.memory[_offset + i] = uint8_t((_value >> (8 * (31 - i))) & 0xff);
518
84.4k
}
519
520
521
void EVMInstructionInterpreter::logTrace(
522
  evmasm::Instruction _instruction,
523
  std::vector<u256> const& _arguments,
524
  bytes const& _data
525
)
526
134k
{
527
134k
  logTrace(
528
134k
    evmasm::instructionInfo(_instruction).name,
529
134k
    SemanticInformation::memory(_instruction) == SemanticInformation::Effect::Write,
530
134k
    _arguments,
531
134k
    _data
532
134k
  );
533
134k
}
534
535
void EVMInstructionInterpreter::logTrace(
536
  std::string const& _pseudoInstruction,
537
  bool _writesToMemory,
538
  std::vector<u256> const& _arguments,
539
  bytes const& _data
540
)
541
134k
{
542
134k
  if (!(_writesToMemory && memWriteTracingDisabled()))
543
49.5k
  {
544
49.5k
    string message = _pseudoInstruction + "(";
545
199k
    for (size_t i = 0; i < _arguments.size(); ++i)
546
150k
      message += (i > 0 ? ", " : "") + formatNumber(_arguments[i]);
547
49.5k
    message += ")";
548
49.5k
    if (!_data.empty())
549
165
      message += " [" + util::toHex(_data) + "]";
550
49.5k
    m_state.trace.emplace_back(std::move(message));
551
49.5k
    if (m_state.maxTraceSize > 0 && m_state.trace.size() >= m_state.maxTraceSize)
552
129
    {
553
129
      m_state.trace.emplace_back("Trace size limit reached.");
554
129
      BOOST_THROW_EXCEPTION(TraceLimitReached());
555
129
    }
556
49.5k
  }
557
134k
}