Skip to content

Commit 1a81274

Browse files
authored
Merge pull request #303 from m-Peter/eth-estimate-gas-handle-reverts
Update `eth_estimateGas` to correctly handle execution reverts
2 parents 4fd9489 + 2192050 commit 1a81274

File tree

2 files changed

+43
-83
lines changed

2 files changed

+43
-83
lines changed

services/requester/requester.go

Lines changed: 7 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ import (
1818
evmTypes "github.com/onflow/flow-go/fvm/evm/types"
1919
"github.com/onflow/flow-go/fvm/systemcontracts"
2020
"github.com/onflow/go-ethereum/common"
21-
gethCore "github.com/onflow/go-ethereum/core"
2221
"github.com/onflow/go-ethereum/core/types"
23-
gethVM "github.com/onflow/go-ethereum/core/vm"
24-
"github.com/onflow/go-ethereum/params"
2522
"github.com/rs/zerolog"
2623
"golang.org/x/sync/errgroup"
2724

@@ -331,7 +328,7 @@ func (e *EVM) Call(
331328
if evmResult.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
332329
return nil, errs.NewRevertError(evmResult.ReturnedData)
333330
}
334-
return nil, getErrorForCode(evmResult.ErrorCode)
331+
return nil, evmTypes.ErrorFromCode(evmResult.ErrorCode)
335332
}
336333

337334
result := evmResult.ReturnedData
@@ -373,16 +370,15 @@ func (e *EVM) EstimateGas(
373370
if err != nil {
374371
return 0, fmt.Errorf("failed to decode EVM result from gas estimation: %w", err)
375372
}
373+
376374
if evmResult.ErrorCode != 0 {
377-
return 0, getErrorForCode(evmResult.ErrorCode)
375+
if evmResult.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
376+
return 0, errs.NewRevertError(evmResult.ReturnedData)
377+
}
378+
return 0, evmTypes.ErrorFromCode(evmResult.ErrorCode)
378379
}
379380

380-
// This minimum gas availability is needed for:
381-
// https://github.com/onflow/go-ethereum/blob/master/core/vm/operations_acl.go#L29-L32
382-
// Note that this is not actually consumed in the end.
383-
// TODO: Consider moving this to `EVM.dryRun`, if we want the
384-
// fix to also apply for the EVM API, on Cadence side.
385-
gasConsumed := evmResult.GasConsumed + params.SstoreSentryGasEIP2200 + 1
381+
gasConsumed := evmResult.GasConsumed
386382

387383
e.logger.Debug().
388384
Uint64("gas", gasConsumed).
@@ -664,75 +660,3 @@ func cadenceStringToBytes(value cadence.Value) ([]byte, error) {
664660

665661
return code, nil
666662
}
667-
668-
// TODO(m-Peter): Consider moving this to flow-go repository
669-
func getErrorForCode(errorCode evmTypes.ErrorCode) error {
670-
switch errorCode {
671-
case evmTypes.ValidationErrCodeGasUintOverflow:
672-
return gethVM.ErrGasUintOverflow
673-
case evmTypes.ValidationErrCodeNonceTooLow:
674-
return gethCore.ErrNonceTooLow
675-
case evmTypes.ValidationErrCodeNonceTooHigh:
676-
return gethCore.ErrNonceTooHigh
677-
case evmTypes.ValidationErrCodeNonceMax:
678-
return gethCore.ErrNonceMax
679-
case evmTypes.ValidationErrCodeGasLimitReached:
680-
return gethCore.ErrGasLimitReached
681-
case evmTypes.ValidationErrCodeInsufficientFundsForTransfer:
682-
return gethCore.ErrInsufficientFundsForTransfer
683-
case evmTypes.ValidationErrCodeMaxInitCodeSizeExceeded:
684-
return gethCore.ErrMaxInitCodeSizeExceeded
685-
case evmTypes.ValidationErrCodeInsufficientFunds:
686-
return gethCore.ErrInsufficientFunds
687-
case evmTypes.ValidationErrCodeIntrinsicGas:
688-
return gethCore.ErrIntrinsicGas
689-
case evmTypes.ValidationErrCodeTxTypeNotSupported:
690-
return gethCore.ErrTxTypeNotSupported
691-
case evmTypes.ValidationErrCodeTipAboveFeeCap:
692-
return gethCore.ErrTipAboveFeeCap
693-
case evmTypes.ValidationErrCodeTipVeryHigh:
694-
return gethCore.ErrTipVeryHigh
695-
case evmTypes.ValidationErrCodeFeeCapVeryHigh:
696-
return gethCore.ErrFeeCapVeryHigh
697-
case evmTypes.ValidationErrCodeFeeCapTooLow:
698-
return gethCore.ErrFeeCapTooLow
699-
case evmTypes.ValidationErrCodeSenderNoEOA:
700-
return gethCore.ErrSenderNoEOA
701-
case evmTypes.ValidationErrCodeBlobFeeCapTooLow:
702-
return gethCore.ErrBlobFeeCapTooLow
703-
case evmTypes.ExecutionErrCodeOutOfGas:
704-
return gethVM.ErrOutOfGas
705-
case evmTypes.ExecutionErrCodeCodeStoreOutOfGas:
706-
return gethVM.ErrCodeStoreOutOfGas
707-
case evmTypes.ExecutionErrCodeDepth:
708-
return gethVM.ErrDepth
709-
case evmTypes.ExecutionErrCodeInsufficientBalance:
710-
return gethVM.ErrInsufficientBalance
711-
case evmTypes.ExecutionErrCodeContractAddressCollision:
712-
return gethVM.ErrContractAddressCollision
713-
case evmTypes.ExecutionErrCodeExecutionReverted:
714-
return gethVM.ErrExecutionReverted
715-
case evmTypes.ExecutionErrCodeMaxInitCodeSizeExceeded:
716-
return gethVM.ErrMaxInitCodeSizeExceeded
717-
case evmTypes.ExecutionErrCodeMaxCodeSizeExceeded:
718-
return gethVM.ErrMaxCodeSizeExceeded
719-
case evmTypes.ExecutionErrCodeInvalidJump:
720-
return gethVM.ErrInvalidJump
721-
case evmTypes.ExecutionErrCodeWriteProtection:
722-
return gethVM.ErrWriteProtection
723-
case evmTypes.ExecutionErrCodeReturnDataOutOfBounds:
724-
return gethVM.ErrReturnDataOutOfBounds
725-
case evmTypes.ExecutionErrCodeGasUintOverflow:
726-
return gethVM.ErrGasUintOverflow
727-
case evmTypes.ExecutionErrCodeInvalidCode:
728-
return gethVM.ErrInvalidCode
729-
case evmTypes.ExecutionErrCodeNonceUintOverflow:
730-
return gethVM.ErrNonceUintOverflow
731-
case evmTypes.ValidationErrCodeMisc:
732-
return fmt.Errorf("validation error: %d", errorCode)
733-
case evmTypes.ExecutionErrCodeMisc:
734-
return fmt.Errorf("execution error: %d", errorCode)
735-
}
736-
737-
return fmt.Errorf("unknown error code: %d", errorCode)
738-
}

tests/web3js/eth_deploy_contract_and_interact_test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,40 @@ it('deploy contract and interact', async() => {
173173
)
174174
}
175175

176+
// check that revert reason for custom error is correctly returned for gas estimation
177+
try {
178+
let callCustomError = deployed.contract.methods.customError().encodeABI()
179+
result = await web3.eth.estimateGas({
180+
from: conf.eoa.address,
181+
to: contractAddress,
182+
data: callCustomError,
183+
gas: 1_000_000,
184+
gasPrice: 0
185+
})
186+
} catch (error) {
187+
assert.equal(error.innerError.message, 'execution reverted')
188+
assert.equal(
189+
error.innerError.data,
190+
'0x9195785a00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001056616c756520697320746f6f206c6f7700000000000000000000000000000000'
191+
)
192+
}
193+
194+
// check that assertion error is correctly returned for gas estimation
195+
try {
196+
let callAssertError = deployed.contract.methods.assertError().encodeABI()
197+
result = await web3.eth.estimateGas({
198+
from: conf.eoa.address,
199+
to: contractAddress,
200+
data: callAssertError,
201+
gas: 1_000_000,
202+
gasPrice: 0
203+
})
204+
} catch (error) {
205+
assert.equal(error.innerError.message, 'execution reverted: Assert Error Message')
206+
assert.equal(
207+
error.innerError.data,
208+
'0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014417373657274204572726f72204d657373616765000000000000000000000000'
209+
)
210+
}
211+
176212
}).timeout(10*1000)

0 commit comments

Comments
 (0)