@@ -154,6 +154,9 @@ namespace HeraVM {
154
154
HERA_DEBUG << " getGasLeft\n " ;
155
155
156
156
static_assert (is_same<decltype (result.gasLeft ), uint64_t >::value, " uint64_t type expected" );
157
+
158
+ takeGas (GasSchedule::base);
159
+
157
160
return Literal (result.gasLeft );
158
161
}
159
162
@@ -164,6 +167,8 @@ namespace HeraVM {
164
167
165
168
storeUint160 (msg.destination , resultOffset);
166
169
170
+ takeGas (GasSchedule::base);
171
+
167
172
return Literal ();
168
173
}
169
174
@@ -175,6 +180,8 @@ namespace HeraVM {
175
180
176
181
evm_address address = loadUint160 (addressOffset);
177
182
evm_uint256be result;
183
+
184
+ takeGas (GasSchedule::balance);
178
185
context->fn_table ->get_balance (&result, context, &address);
179
186
storeUint128 (result, resultOffset);
180
187
@@ -188,6 +195,8 @@ namespace HeraVM {
188
195
HERA_DEBUG << " getBlockHash " << hex << number << " " << resultOffset << dec << " \n " ;
189
196
190
197
evm_uint256be blockhash;
198
+
199
+ takeGas (GasSchedule::blockhash);
191
200
context->fn_table ->get_block_hash (&blockhash, context, number);
192
201
storeUint256 (blockhash, resultOffset);
193
202
@@ -196,6 +205,9 @@ namespace HeraVM {
196
205
197
206
if (import->base == Name (" getCallDataSize" )) {
198
207
HERA_DEBUG << " callDataSize\n " ;
208
+
209
+ takeGas (GasSchedule::base);
210
+
199
211
return Literal (static_cast <uint32_t >(msg.input_size ));
200
212
}
201
213
@@ -206,6 +218,13 @@ namespace HeraVM {
206
218
207
219
HERA_DEBUG << " callDataCopy " << hex << resultOffset << " " << dataOffset << " " << length << dec << " \n " ;
208
220
221
+ heraAssert (ffs (GasSchedule::copy) + (ffs (length) - 5 ) <= 64 , " Gas charge overflow" );
222
+ heraAssert (
223
+ numeric_limits<uint64_t >::max () - GasSchedule::verylow >= GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ),
224
+ " Gas charge overflow"
225
+ );
226
+ takeGas (GasSchedule::verylow + GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ));
227
+
209
228
vector<uint8_t > input (msg.input_data , msg.input_data + msg.input_size );
210
229
storeMemory (input, dataOffset, resultOffset, length);
211
230
@@ -217,6 +236,7 @@ namespace HeraVM {
217
236
218
237
HERA_DEBUG << " getCaller " << hex << resultOffset << dec << " \n " ;
219
238
239
+ takeGas (GasSchedule::base);
220
240
storeUint160 (msg.sender , resultOffset);
221
241
222
242
return Literal ();
@@ -227,6 +247,7 @@ namespace HeraVM {
227
247
228
248
HERA_DEBUG << " getCallValue " << hex << resultOffset << dec << " \n " ;
229
249
250
+ takeGas (GasSchedule::base);
230
251
storeUint128 (msg.value , resultOffset);
231
252
232
253
return Literal ();
@@ -239,6 +260,12 @@ namespace HeraVM {
239
260
240
261
HERA_DEBUG << " codeCopy " << hex << resultOffset << " " << codeOffset << " " << length << dec << " \n " ;
241
262
263
+ heraAssert (ffs (GasSchedule::copy) + (ffs (length) - 5 ) <= 64 , " Gas charge overflow" );
264
+ heraAssert (
265
+ numeric_limits<uint64_t >::max () - GasSchedule::verylow >= GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ),
266
+ " Gas charge overflow"
267
+ );
268
+ takeGas (GasSchedule::verylow + GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ));
242
269
storeMemory (code, codeOffset, resultOffset, length);
243
270
244
271
return Literal ();
@@ -247,6 +274,8 @@ namespace HeraVM {
247
274
if (import->base == Name (" getCodeSize" )) {
248
275
HERA_DEBUG << " getCodeSize\n " ;
249
276
277
+ takeGas (GasSchedule::base);
278
+
250
279
return Literal (static_cast <uint32_t >(code.size ()));
251
280
}
252
281
@@ -262,8 +291,10 @@ namespace HeraVM {
262
291
const uint8_t *code;
263
292
size_t code_size = context->fn_table ->get_code (&code, context, &address);
264
293
294
+ heraAssert (ffs (GasSchedule::copy) + (ffs (length) - 5 ) <= 64 , " Gas charge overflow" );
295
+ heraAssert (numeric_limits<uint64_t >::max () - GasSchedule::extcode >= GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ), " Gas charge overflow" );
296
+ takeGas (GasSchedule::extcode + GasSchedule::copy * ((uint64_t (length) + 31 ) / 32 ));
265
297
// NOTE: code will be freed by the callee (client)
266
-
267
298
// FIXME: optimise this so not vector needs to be created
268
299
storeMemory (vector<uint8_t >(code, code + code_size), codeOffset, resultOffset, length);
269
300
@@ -276,6 +307,7 @@ namespace HeraVM {
276
307
HERA_DEBUG << " getExternalCodeSize " << hex << addressOffset << dec << " \n " ;
277
308
278
309
evm_address address = loadUint160 (addressOffset);
310
+ takeGas (GasSchedule::extcode);
279
311
size_t code_size = context->fn_table ->get_code (NULL , context, &address);
280
312
281
313
return Literal (static_cast <uint32_t >(code_size));
@@ -287,6 +319,8 @@ namespace HeraVM {
287
319
HERA_DEBUG << " getBlockCoinbase " << hex << resultOffset << dec << " \n " ;
288
320
289
321
evm_tx_context tx_context;
322
+
323
+ takeGas (GasSchedule::base);
290
324
context->fn_table ->get_tx_context (&tx_context, context);
291
325
storeUint160 (tx_context.block_coinbase , resultOffset);
292
326
@@ -299,6 +333,8 @@ namespace HeraVM {
299
333
HERA_DEBUG << " getBlockDifficulty " << hex << offset << dec << " \n " ;
300
334
301
335
evm_tx_context tx_context;
336
+
337
+ takeGas (GasSchedule::base);
302
338
context->fn_table ->get_tx_context (&tx_context, context);
303
339
storeUint256 (tx_context.block_difficulty , offset);
304
340
@@ -309,9 +345,12 @@ namespace HeraVM {
309
345
HERA_DEBUG << " getBlockGasLimit\n " ;
310
346
311
347
evm_tx_context tx_context;
348
+
349
+ takeGas (GasSchedule::base);
312
350
context->fn_table ->get_tx_context (&tx_context, context);
313
351
314
352
static_assert (is_same<decltype (tx_context.block_gas_limit ), int64_t >::value, " int64_t type expected" );
353
+
315
354
return Literal (tx_context.block_gas_limit );
316
355
}
317
356
@@ -321,6 +360,8 @@ namespace HeraVM {
321
360
HERA_DEBUG << " getTxGasPrice " << hex << valueOffset << dec << " \n " ;
322
361
323
362
evm_tx_context tx_context;
363
+
364
+ takeGas (GasSchedule::base);
324
365
context->fn_table ->get_tx_context (&tx_context, context);
325
366
storeUint128 (tx_context.tx_gas_price , valueOffset);
326
367
@@ -335,7 +376,6 @@ namespace HeraVM {
335
376
HERA_DEBUG << " log " << hex << dataOffset << " " << length << " " << numberOfTopics << dec << " \n " ;
336
377
337
378
heraAssert (!(msg.flags & EVM_STATIC), " \" log\" attempted in static mode" );
338
-
339
379
heraAssert (numberOfTopics <= 4 , " Too many topics specified" );
340
380
341
381
evm_uint256be topics[numberOfTopics];
@@ -347,6 +387,12 @@ namespace HeraVM {
347
387
vector<uint8_t > data (length);
348
388
loadMemory (dataOffset, data, length);
349
389
390
+ heraAssert (ffs (length) + ffs (GasSchedule::logData) <= 64 , " Gas charge overflow" );
391
+ heraAssert (
392
+ numeric_limits<uint64_t >::max () - (GasSchedule::log + GasSchedule::logTopic * numberOfTopics) >= static_cast <uint64_t >(length) * GasSchedule::logData,
393
+ " Gas charge overflow"
394
+ );
395
+ takeGas (GasSchedule::log + (length * GasSchedule::logData) + (GasSchedule::logTopic * numberOfTopics));
350
396
context->fn_table ->emit_log (context, &msg.destination , data.data (), length, topics, numberOfTopics);
351
397
352
398
return Literal ();
@@ -356,19 +402,25 @@ namespace HeraVM {
356
402
HERA_DEBUG << " getBlockNumber\n " ;
357
403
358
404
evm_tx_context tx_context;
405
+
406
+ takeGas (GasSchedule::base);
359
407
context->fn_table ->get_tx_context (&tx_context, context);
360
408
361
409
static_assert (is_same<decltype (tx_context.block_number ), int64_t >::value, " int64_t type expected" );
410
+
362
411
return Literal (tx_context.block_number );
363
412
}
364
413
365
414
if (import->base == Name (" getBlockTimestamp" )) {
366
415
HERA_DEBUG << " getBlockTimestamp\n " ;
367
416
368
417
evm_tx_context tx_context;
418
+
419
+ takeGas (GasSchedule::base);
369
420
context->fn_table ->get_tx_context (&tx_context, context);
370
421
371
422
static_assert (is_same<decltype (tx_context.block_timestamp ), int64_t >::value, " int64_t type expected" );
423
+
372
424
return Literal (tx_context.block_timestamp );
373
425
}
374
426
@@ -378,6 +430,8 @@ namespace HeraVM {
378
430
HERA_DEBUG << " getTxOrigin " << hex << resultOffset << dec << " \n " ;
379
431
380
432
evm_tx_context tx_context;
433
+
434
+ takeGas (GasSchedule::base);
381
435
context->fn_table ->get_tx_context (&tx_context, context);
382
436
storeUint160 (tx_context.tx_origin , resultOffset);
383
437
@@ -394,8 +448,8 @@ namespace HeraVM {
394
448
395
449
evm_uint256be path = loadUint256 (pathOffset);
396
450
evm_uint256be value = loadUint256 (valueOffset);
397
-
398
451
evm_uint256be current;
452
+
399
453
context->fn_table ->get_storage (¤t, context, &msg.destination , &path);
400
454
401
455
// We do not need to take care about the delete case (gas refund), the client does it.
@@ -417,8 +471,9 @@ namespace HeraVM {
417
471
HERA_DEBUG << " storageLoad " << hex << pathOffset << " " << resultOffset << dec << " \n " ;
418
472
419
473
evm_uint256be path = loadUint256 (pathOffset);
420
-
421
474
evm_uint256be result;
475
+
476
+ takeGas (GasSchedule::storageLoad);
422
477
context->fn_table ->get_storage (&result, context, &msg.destination , &path);
423
478
424
479
storeUint256 (result, resultOffset);
@@ -442,6 +497,9 @@ namespace HeraVM {
442
497
443
498
if (import->base == Name (" getReturnDataSize" )) {
444
499
HERA_DEBUG << " getReturnDataSize\n " ;
500
+
501
+ takeGas (GasSchedule::base);
502
+
445
503
return Literal (static_cast <uint32_t >(lastReturnData.size ()));
446
504
}
447
505
@@ -452,6 +510,7 @@ namespace HeraVM {
452
510
453
511
HERA_DEBUG << " returnDataCopy " << hex << dataOffset << " " << offset << " " << size << dec << " \n " ;
454
512
513
+ takeGas (GasSchedule::verylow);
455
514
storeMemory (lastReturnData, offset, dataOffset, size);
456
515
457
516
return Literal ();
@@ -482,7 +541,7 @@ namespace HeraVM {
482
541
valueOffset = arguments[2 ].geti32 ();
483
542
dataOffset = arguments[3 ].geti32 ();
484
543
dataLength = arguments[4 ].geti32 ();
485
-
544
+
486
545
call_message.sender = msg.destination ;
487
546
call_message.value = loadUint128 (valueOffset);
488
547
call_message.kind = (import->base == Name (" callCode" )) ? EVM_CALLCODE : EVM_CALL;
@@ -527,6 +586,13 @@ namespace HeraVM {
527
586
}
528
587
529
588
evm_result call_result;
589
+
590
+ if (import->base == Name (" call" ) && !context->fn_table ->account_exists (context, &call_message.destination ))
591
+ takeGas (GasSchedule::callNewAccount);
592
+ if (!isZeroUint256 (call_message.value ))
593
+ takeGas (GasSchedule::valuetransfer);
594
+ takeGas (call_message.gas );
595
+ takeGas (GasSchedule::call);
530
596
context->fn_table ->call (&call_result, context, &call_message);
531
597
532
598
if (call_result.output_data ) {
@@ -538,6 +604,9 @@ namespace HeraVM {
538
604
if (call_result.release )
539
605
call_result.release (&call_result);
540
606
607
+ /* Return unspent gas */
608
+ result.gasLeft += call_result.gas_left ;
609
+
541
610
switch (call_result.status_code ) {
542
611
case EVM_SUCCESS:
543
612
return Literal (uint32_t (0 ));
@@ -583,7 +652,11 @@ namespace HeraVM {
583
652
create_message.flags = 0 ;
584
653
585
654
evm_result create_result;
655
+
656
+ takeGas (create_message.gas );
657
+ takeGas (GasSchedule::create);
586
658
context->fn_table ->call (&create_result, context, &create_message);
659
+
587
660
if (create_result.status_code == EVM_SUCCESS) {
588
661
storeUint160 (create_result.create_address , resultOffset);
589
662
lastReturnData.clear ();
@@ -615,6 +688,9 @@ namespace HeraVM {
615
688
616
689
evm_address address = loadUint160 (addressOffset);
617
690
691
+ if (!context->fn_table ->account_exists (context, &address))
692
+ takeGas (GasSchedule::callNewAccount);
693
+ takeGas (GasSchedule::selfdestruct);
618
694
context->fn_table ->selfdestruct (context, &msg.destination , &address);
619
695
620
696
return Literal ();
0 commit comments