Skip to content

Commit

Permalink
Avoid unnecessary 100 gas cost in CALL & add missing write-event for …
Browse files Browse the repository at this point in the history
…CODEHASH (#508)

* avoid extra 100 gas in value-bearing CALL

Signed-off-by: Ignacio Hagopian <[email protected]>

* missing codeHash write event

Signed-off-by: Ignacio Hagopian <[email protected]>

* feedback

Signed-off-by: Ignacio Hagopian <[email protected]>

* Update core/vm/evm.go

Co-authored-by: Guillaume Ballet <[email protected]>

---------

Signed-off-by: Ignacio Hagopian <[email protected]>
Co-authored-by: Guillaume Ballet <[email protected]>
  • Loading branch information
jsign and gballet authored Oct 15, 2024
1 parent f4733ce commit 4b91d84
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 7 deletions.
4 changes: 2 additions & 2 deletions core/state/access_witness.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ func (aw *AccessWitness) TouchAndChargeValueTransfer(callerAddr, targetAddr []by
if !ok {
return false
}
_, ok = aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, useGasFn)
return ok
chargedGas, ok := aw.touchAddressAndChargeGas(targetAddr, zeroTreeIndex, utils.BasicDataLeafKey, true, useGasFn)
return ok && (chargedGas > 0 || useGasFn(params.WarmStorageReadCostEIP2929))
}

// TouchAndChargeContractCreateCheck charges access costs before
Expand Down
11 changes: 8 additions & 3 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,15 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
debug := evm.Config.Tracer != nil

if !evm.StateDB.Exist(addr) {
if !isPrecompile && evm.chainRules.IsEIP4762 {
// add proof of absence to witness
if !isPrecompile && evm.chainRules.IsEIP4762 && value.Sign() != 0 {
gc := gasConsumer{availableGas: gas}
ok := evm.Accesses.TouchFullAccount(addr.Bytes(), false, gc.consumeGas)
// At this point, the read costs have already been charged, either because this
// is a direct tx call, in which case it's covered by the intrinsic gas, or because
// of a CALL instruction, in which case BASIC_DATA has been added to the access
// list in write mode. If there is enough gas paying for the addition of the code
// hash leaf to the access list, then account creation will proceed unimpaired.
// Thus, only pay for the creation of the code hash leaf here.
ok := evm.Accesses.TouchCodeHash(addr.Bytes(), true, gc.consumeGas)
if !ok {
evm.StateDB.RevertToSnapshot(snapshot)
return nil, 0, ErrOutOfGas
Expand Down
4 changes: 2 additions & 2 deletions core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,9 @@ func getMemSize(operation *operation, stack *Stack) (uint64, error) {
}

func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byte, error) {
transfersValue := !scope.Stack.Back(2).IsZero()
if interpreter.evm.chainRules.IsEIP4762 {
address := common.Address(scope.Stack.Back(1).Bytes20())
transfersValue := !scope.Stack.Back(2).IsZero()

// If value is transferred, it is charged before 1/64th
// is subtracted from the available gas pool.
Expand All @@ -814,7 +814,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
}
}

if interpreter.evm.chainRules.IsEIP4762 && !chargeCallVariantEIP4762(interpreter.evm, scope) {
if interpreter.evm.chainRules.IsEIP4762 && !transfersValue && !chargeCallVariantEIP4762(interpreter.evm, scope) {
return nil, ErrOutOfGas
}
memSize, err := getMemSize(interpreter.table[CALL], scope.Stack)
Expand Down

0 comments on commit 4b91d84

Please sign in to comment.