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
2 changes: 2 additions & 0 deletions src/compiler/evm_frontend/evm_imported.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ const uint8_t *evmHandleCreateInternal(zen::runtime::EVMInstance *Instance,
if (GasUsed != 0) {
Instance->chargeGas(GasUsed);
}
// Track subcall refund (may be negative)
Instance->addGasRefund(Result.gas_refund);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when will the gas refund negative

Copy link
Contributor Author

@abmcar abmcar Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It becomes negative under EIP-2200 net SSTORE accounting when a later storage change cancels a previously accrued refund.
EVMC allows per-call gas_refund to be negative; we just accumulate deltas and the tx-level cap is applied later.


std::vector<uint8_t> ReturnData(Result.output_data,
Expand Down Expand Up @@ -956,6 +957,7 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
Instance->chargeGas(GasUsed);
}

// Track subcall refund (may be negative)
Instance->addGasRefund(Result.gas_refund);

// Copy return data to memory if output area is specified.
Expand Down
2 changes: 1 addition & 1 deletion src/evm/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ struct EVMFrame {
evmc_message Msg = {};
evmc::Host *Host = nullptr;
evmc_tx_context MTx = {};
uint64_t GasRefundSnapshot = 0;
int64_t GasRefundSnapshot = 0;

size_t Sp = 0;
uint64_t Pc = 0;
Expand Down
7 changes: 2 additions & 5 deletions src/evm/opcode_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1461,11 +1461,8 @@ void CallHandler::doExecute() {
return;
}

if (Result.gas_refund > 0) {
// Track subcall refund at Instance level
Context->getInstance()->addGasRefund(Result.gas_refund);
}

// Track subcall refund at Instance level (may be negative)
Context->getInstance()->addGasRefund(Result.gas_refund);
Context->setStatus(EVMC_SUCCESS);
}

Expand Down
8 changes: 4 additions & 4 deletions src/runtime/evm_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
void chargeGas(uint64_t GasCost);
void addGas(uint64_t GasAmount);

void addGasRefund(uint64_t Amount) { GasRefund += Amount; }
void setGasRefund(uint64_t Amount) { GasRefund = Amount; }
uint64_t getGasRefund() const { return GasRefund; }
void addGasRefund(int64_t Amount) { GasRefund += Amount; }
void setGasRefund(int64_t Amount) { GasRefund = Amount; }
int64_t getGasRefund() const { return GasRefund; }
void restoreGasRefundSnapshot() {
if (!GasRefundStack.empty()) {
GasRefund = GasRefundStack.back();
Expand Down Expand Up @@ -288,7 +288,7 @@ class EVMInstance final : public RuntimeObject<EVMInstance> {
newEVMInstance(Isolation &Iso, const EVMModule &Mod, uint64_t GasLimit = 0);

const EVMModule *Mod = nullptr;
uint64_t GasRefund = 0;
int64_t GasRefund = 0;
// memory
uint8_t *MemoryBase = nullptr;
uint64_t MemorySize = 0;
Expand Down