Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/gas.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define G_CALLDATAZERO 4
#define G_CALLDATA 16
#define G_CALLDATANONZERO 12
#define G_TXDATA_FLOOR 10
#define G_LOG 375
#define G_LOGDATA 8
#define G_LOGTOPIC 375
Expand Down
30 changes: 22 additions & 8 deletions src/evm.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,18 @@ static inline uint64_t calldataGas(const data_t *calldata) {
return gas;
}

// EIP-7623: a transaction's gasUsed is at least this
// calldata tokens count zero bytes once and nonzero bytes four times, so calldataGas is G_CALLDATAZERO per token
static inline uint64_t floorGas(const data_t *calldata) {
return G_TX + calldataGas(calldata) / G_CALLDATAZERO * G_TXDATA_FLOOR;
}

static inline void applyFloor(result_t *result, uint64_t gas, uint64_t minGasUsed) {
if (gas - result->gasRemaining < minGasUsed) {
result->gasRemaining = gas - minGasUsed;
}
}

// In the yellow paper, this is the R function.
static inline uint64_t initcodeGas(const data_t *initcode) {
return G_INITCODEWORD * ((initcode->size + 31) >> 5); // EIP 3860: 2 gas per word
Expand Down Expand Up @@ -2486,12 +2498,11 @@ static result_t _evmConstruct(account_t *fromAccount, account_t *to, uint64_t ga
context_t *callContext = callstack.next;
callContext->gas = gas;
if (callstack.next == callstack.bottom) {
callContext->gas -= G_TXCREATE + G_TX;
callContext->gas -= calldataGas(&input);
callContext->gas -= initcodeGas(&input);
if (gas < callContext->gas) {
// underflow indicates insufficient initial gas
fprintf(stderr, "Out of gas while initializing initcode (have %" PRIu64 " need %" PRIu64 ")\n", gas, gas - callContext->gas);
uint64_t intrinsicGas = G_TXCREATE + G_TX + calldataGas(&input) + initcodeGas(&input);
uint64_t minGasUsed = floorGas(&input);
callContext->gas -= intrinsicGas;
if (gas < intrinsicGas || gas < minGasUsed) {
fprintf(stderr, "Out of gas while initializing initcode (have %" PRIu64 " need %" PRIu64 ")\n", gas, intrinsicGas > minGasUsed ? intrinsicGas : minGasUsed);
evmRevert(&callContext->stateChanges);
result_t result;
result.gasRemaining = 0;
Expand Down Expand Up @@ -2570,6 +2581,7 @@ static result_t _evmConstruct(account_t *fromAccount, account_t *to, uint64_t ga
}
result.gasRemaining += refund;
refundCounter = 0;
applyFloor(&result, gas, floorGas(&input));
}

return result;
Expand Down Expand Up @@ -2602,8 +2614,9 @@ result_t txCall(address_t from, uint64_t gas, address_t to, val_t value, data_t
}
accessList = accessList->prev;
}
if (gas < intrinsicGas) {
fprintf(stderr, "Insufficient intrinsic gas %" PRIu64 " (need %" PRIu64 ")\n", gas, intrinsicGas);
uint64_t minGasUsed = floorGas(&input);
if (gas < intrinsicGas || gas < minGasUsed) {
fprintf(stderr, "Insufficient intrinsic gas %" PRIu64 " (need %" PRIu64 ")\n", gas, intrinsicGas > minGasUsed ? intrinsicGas : minGasUsed);
result_t result;
result.gasRemaining = 0;
clear256(&result.status);
Expand All @@ -2629,6 +2642,7 @@ result_t txCall(address_t from, uint64_t gas, address_t to, val_t value, data_t
}
result.gasRemaining += refund;
refundCounter = 0;
applyFloor(&result, originalGas, minGasUsed);

evmIteration++;
blockEnd();
Expand Down
4 changes: 2 additions & 2 deletions tst/evm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1127,7 +1127,7 @@ void test_callEmpty() {
};
address_t from = AddressFromHex42("0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1");
address_t to = AddressFromHex42("0x4a6f6B9fF1fc974096f9063a45Fd12bD5B928AD1");
uint64_t gas = 21432;
uint64_t gas = 22080;
val_t value;
value[0] = 0;
value[1] = 0;
Expand Down Expand Up @@ -1330,7 +1330,7 @@ void test_extcodecopy() {
}
assert(examineFirstAccount.gasRemaining == 0);

gas = 21617;
gas = 21920;
input.content = locations[3].address - 12;
result_t examineSecondAccount = txCall(from, gas, to, value, input, NULL);
assert(UPPER(UPPER(examineSecondAccount.status)) == 0);
Expand Down
7 changes: 7 additions & 0 deletions tst/extcodehash.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@
"input": "0x0000000000000000000000000000000000000000000000000000000000000001",
"gasUsed": "0x53eb",
"output": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47042745b147133dc2dae253631d9081ba4c329248e74d1b9f10e38efe1385af484"
},
{
"name": "tx.origin, calldata floor (sepolia 0xe3d091e1cbcdb866699e9fe5bd0d38223e75238f2ff1434477126dd5013c3aff)",
"from": "0x3b559cf662fdfe485ec216c036d4cee91fbd1d39",
"input": "0x0000000000000000000000003b559cf662fdfe485ec216c036d4cee91fbd1d39",
"gasUsed": "0x55a0",
"output": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47042745b147133dc2dae253631d9081ba4c329248e74d1b9f10e38efe1385af484"
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion tst/quine.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
},
{
"name": "ignores calldata",
"gasUsed": "0x525b",
"gasUsed": "0x52a8",
"input": "0xdeadbeef",
"output": "0x383d3d39383df3"
}
Expand Down
Loading