4545const minFlowBalance = 2
4646const blockGasLimit = 120_000_000
4747
48- // estimateGasErrorRatio is the amount of overestimation eth_estimateGas
49- // is allowed to produce in order to speed up calculations.
50- const estimateGasErrorRatio = 0.015
51-
5248type Requester interface {
5349 // SendRawTransaction will submit signed transaction data to the network.
5450 // The submitted EVM transaction hash is returned.
@@ -62,7 +58,7 @@ type Requester interface {
6258 // Note, this function doesn't make and changes in the state/blockchain and is
6359 // useful to execute and retrieve values.
6460 Call (
65- tx * types.DynamicFeeTx ,
61+ tx * types.LegacyTx ,
6662 from common.Address ,
6763 height uint64 ,
6864 stateOverrides * ethTypes.StateOverride ,
@@ -72,7 +68,7 @@ type Requester interface {
7268 // Note, this function doesn't make any changes in the state/blockchain and is
7369 // useful to executed and retrieve the gas consumption and possible failures.
7470 EstimateGas (
75- tx * types.DynamicFeeTx ,
71+ tx * types.LegacyTx ,
7672 from common.Address ,
7773 height uint64 ,
7874 stateOverrides * ethTypes.StateOverride ,
@@ -328,7 +324,7 @@ func (e *EVM) GetStorageAt(
328324}
329325
330326func (e * EVM ) Call (
331- tx * types.DynamicFeeTx ,
327+ tx * types.LegacyTx ,
332328 from common.Address ,
333329 height uint64 ,
334330 stateOverrides * ethTypes.StateOverride ,
@@ -338,113 +334,42 @@ func (e *EVM) Call(
338334 return nil , err
339335 }
340336
341- resultSummary := result .ResultSummary ()
342- if resultSummary .ErrorCode != 0 {
343- if resultSummary .ErrorCode == evmTypes .ExecutionErrCodeExecutionReverted {
344- return nil , errs .NewRevertError (resultSummary .ReturnedData )
345- }
346- return nil , errs .NewFailedTransactionError (resultSummary .ErrorMessage )
347- }
348-
349- return result .ReturnedData , nil
337+ return result .ReturnedData , err
350338}
351339
352340func (e * EVM ) EstimateGas (
353- tx * types.DynamicFeeTx ,
341+ tx * types.LegacyTx ,
354342 from common.Address ,
355343 height uint64 ,
356344 stateOverrides * ethTypes.StateOverride ,
357345) (uint64 , error ) {
358- // Note: The following algorithm, is largely inspired from
359- // https://github.com/onflow/go-ethereum/blob/master/eth/gasestimator/gasestimator.go#L49-L192,
360- // and adapted to fit our use-case.
361- // Binary search the gas limit, as it may need to be higher than the amount used
362- var (
363- failingGasLimit uint64 // lowest-known gas limit where tx execution fails
364- passingGasLimit uint64 // lowest-known gas limit where tx execution succeeds
365- )
366- // Determine the highest gas limit that can be used during the estimation.
367- passingGasLimit = blockGasLimit
368- if tx .Gas >= gethParams .TxGas {
369- passingGasLimit = tx .Gas
370- }
371- tx .Gas = passingGasLimit
372- // We first execute the transaction at the highest allowable gas limit,
373- // since if this fails we can return error immediately.
374346 result , err := e .dryRunTx (tx , from , height , stateOverrides )
375347 if err != nil {
376348 return 0 , err
377349 }
378- resultSummary := result .ResultSummary ()
379- if resultSummary .ErrorCode != 0 {
380- if resultSummary .ErrorCode == evmTypes .ExecutionErrCodeExecutionReverted {
381- return 0 , errs .NewRevertError (resultSummary .ReturnedData )
382- }
383- return 0 , errs .NewFailedTransactionError (resultSummary .ErrorMessage )
384- }
385-
386- // For almost any transaction, the gas consumed by the unconstrained execution
387- // above lower-bounds the gas limit required for it to succeed. One exception
388- // is those that explicitly check gas remaining in order to execute within a
389- // given limit, but we probably don't want to return the lowest possible gas
390- // limit for these cases anyway.
391- failingGasLimit = result .GasConsumed - 1
392-
393- // There's a fairly high chance for the transaction to execute successfully
394- // with gasLimit set to the first execution's GasConsumed + GasRefund.
395- // Explicitly check that gas amount and use as a limit for the binary search.
396- optimisticGasLimit := (result .GasConsumed + result .GasRefund + gethParams .CallStipend ) * 64 / 63
397- if optimisticGasLimit < passingGasLimit {
398- tx .Gas = optimisticGasLimit
399- result , err = e .dryRunTx (tx , from , height , stateOverrides )
400- if err != nil {
401- // This should not happen under normal conditions since if we make it this far the
402- // transaction had run without error at least once before.
403- return 0 , err
404- }
405- resultSummary := result .ResultSummary ()
406- if resultSummary .ErrorCode == evmTypes .ExecutionErrCodeOutOfGas {
407- failingGasLimit = optimisticGasLimit
408- } else {
409- passingGasLimit = optimisticGasLimit
410- }
411- }
412350
413- // Binary search for the smallest gas limit that allows the tx to execute successfully.
414- for failingGasLimit + 1 < passingGasLimit {
415- // It is a bit pointless to return a perfect estimation, as changing
416- // network conditions require the caller to bump it up anyway. Since
417- // wallets tend to use 20-25% bump, allowing a small approximation
418- // error is fine (as long as it's upwards).
419- if float64 (passingGasLimit - failingGasLimit )/ float64 (passingGasLimit ) < estimateGasErrorRatio {
420- break
421- }
422- mid := (passingGasLimit + failingGasLimit ) / 2
423- if mid > failingGasLimit * 2 {
424- // Most txs don't need much higher gas limit than their gas used, and most txs don't
425- // require near the full block limit of gas, so the selection of where to bisect the
426- // range here is skewed to favor the low side.
427- mid = failingGasLimit * 2
428- }
429- tx .Gas = mid
430- result , err = e .dryRunTx (tx , from , height , stateOverrides )
431- if err != nil {
432- return 0 , err
433- }
434- resultSummary := result .ResultSummary ()
435- if resultSummary .ErrorCode == evmTypes .ExecutionErrCodeOutOfGas {
436- failingGasLimit = mid
437- } else {
438- passingGasLimit = mid
439- }
440- }
351+ if result .Successful () {
352+ // As mentioned in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md#specification
353+ // Define "all but one 64th" of N as N - floor(N / 64).
354+ // If a call asks for more gas than the maximum allowed amount
355+ // (i.e. the total amount of gas remaining in the parent after subtracting
356+ // the gas cost of the call and memory expansion), do not return an OOG error;
357+ // instead, if a call asks for more gas than all but one 64th of the maximum
358+ // allowed amount, call with all but one 64th of the maximum allowed amount of
359+ // gas (this is equivalent to a version of EIP-901 plus EIP-1142).
360+ // CREATE only provides all but one 64th of the parent gas to the child call.
361+ result .GasConsumed = AddOne64th (result .GasConsumed )
362+
363+ // Adding `gethParams.SstoreSentryGasEIP2200` is needed for this condition:
364+ // https://github.com/onflow/go-ethereum/blob/master/core/vm/operations_acl.go#L29-L32
365+ result .GasConsumed += gethParams .SstoreSentryGasEIP2200
441366
442- if tx . AccessList != nil {
443- passingGasLimit += uint64 ( len ( tx . AccessList )) * gethParams . TxAccessListAddressGas
444- passingGasLimit += uint64 ( tx . AccessList . StorageKeys ()) * gethParams . TxAccessListStorageKeyGas
367+ // Take into account any gas refunds, which are calculated only after
368+ // transaction execution.
369+ result . GasConsumed += result . GasRefund
445370 }
446371
447- return passingGasLimit , nil
372+ return result . GasConsumed , err
448373}
449374
450375func (e * EVM ) GetCode (
@@ -536,7 +461,7 @@ func (e *EVM) evmToCadenceHeight(height uint64) (uint64, error) {
536461}
537462
538463func (e * EVM ) dryRunTx (
539- tx * types.DynamicFeeTx ,
464+ tx * types.LegacyTx ,
540465 from common.Address ,
541466 height uint64 ,
542467 stateOverrides * ethTypes.StateOverride ,
@@ -596,6 +521,14 @@ func (e *EVM) dryRunTx(
596521 return nil , err
597522 }
598523
524+ resultSummary := result .ResultSummary ()
525+ if resultSummary .ErrorCode != 0 {
526+ if resultSummary .ErrorCode == evmTypes .ExecutionErrCodeExecutionReverted {
527+ return nil , errs .NewRevertError (resultSummary .ReturnedData )
528+ }
529+ return nil , errs .NewFailedTransactionError (resultSummary .ErrorMessage )
530+ }
531+
599532 return result , nil
600533}
601534
0 commit comments