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
90 changes: 7 additions & 83 deletions services/requester/requester.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,7 @@ import (
evmTypes "github.com/onflow/flow-go/fvm/evm/types"
"github.com/onflow/flow-go/fvm/systemcontracts"
"github.com/onflow/go-ethereum/common"
gethCore "github.com/onflow/go-ethereum/core"
"github.com/onflow/go-ethereum/core/types"
gethVM "github.com/onflow/go-ethereum/core/vm"
"github.com/onflow/go-ethereum/params"
"github.com/rs/zerolog"
"golang.org/x/sync/errgroup"

Expand Down Expand Up @@ -331,7 +328,7 @@ func (e *EVM) Call(
if evmResult.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
return nil, errs.NewRevertError(evmResult.ReturnedData)
}
return nil, getErrorForCode(evmResult.ErrorCode)
return nil, evmTypes.ErrorFromCode(evmResult.ErrorCode)
}

result := evmResult.ReturnedData
Expand Down Expand Up @@ -373,16 +370,15 @@ func (e *EVM) EstimateGas(
if err != nil {
return 0, fmt.Errorf("failed to decode EVM result from gas estimation: %w", err)
}

if evmResult.ErrorCode != 0 {
return 0, getErrorForCode(evmResult.ErrorCode)
if evmResult.ErrorCode == evmTypes.ExecutionErrCodeExecutionReverted {
return 0, errs.NewRevertError(evmResult.ReturnedData)
}
return 0, evmTypes.ErrorFromCode(evmResult.ErrorCode)
}

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

Choose a reason for hiding this comment

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

so we removed this because we handle it in the EVM core now?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, exactly, this is done by EVM.dryRun now.

gasConsumed := evmResult.GasConsumed

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

return code, nil
}

// TODO(m-Peter): Consider moving this to flow-go repository
func getErrorForCode(errorCode evmTypes.ErrorCode) error {
switch errorCode {
case evmTypes.ValidationErrCodeGasUintOverflow:
return gethVM.ErrGasUintOverflow
case evmTypes.ValidationErrCodeNonceTooLow:
return gethCore.ErrNonceTooLow
case evmTypes.ValidationErrCodeNonceTooHigh:
return gethCore.ErrNonceTooHigh
case evmTypes.ValidationErrCodeNonceMax:
return gethCore.ErrNonceMax
case evmTypes.ValidationErrCodeGasLimitReached:
return gethCore.ErrGasLimitReached
case evmTypes.ValidationErrCodeInsufficientFundsForTransfer:
return gethCore.ErrInsufficientFundsForTransfer
case evmTypes.ValidationErrCodeMaxInitCodeSizeExceeded:
return gethCore.ErrMaxInitCodeSizeExceeded
case evmTypes.ValidationErrCodeInsufficientFunds:
return gethCore.ErrInsufficientFunds
case evmTypes.ValidationErrCodeIntrinsicGas:
return gethCore.ErrIntrinsicGas
case evmTypes.ValidationErrCodeTxTypeNotSupported:
return gethCore.ErrTxTypeNotSupported
case evmTypes.ValidationErrCodeTipAboveFeeCap:
return gethCore.ErrTipAboveFeeCap
case evmTypes.ValidationErrCodeTipVeryHigh:
return gethCore.ErrTipVeryHigh
case evmTypes.ValidationErrCodeFeeCapVeryHigh:
return gethCore.ErrFeeCapVeryHigh
case evmTypes.ValidationErrCodeFeeCapTooLow:
return gethCore.ErrFeeCapTooLow
case evmTypes.ValidationErrCodeSenderNoEOA:
return gethCore.ErrSenderNoEOA
case evmTypes.ValidationErrCodeBlobFeeCapTooLow:
return gethCore.ErrBlobFeeCapTooLow
case evmTypes.ExecutionErrCodeOutOfGas:
return gethVM.ErrOutOfGas
case evmTypes.ExecutionErrCodeCodeStoreOutOfGas:
return gethVM.ErrCodeStoreOutOfGas
case evmTypes.ExecutionErrCodeDepth:
return gethVM.ErrDepth
case evmTypes.ExecutionErrCodeInsufficientBalance:
return gethVM.ErrInsufficientBalance
case evmTypes.ExecutionErrCodeContractAddressCollision:
return gethVM.ErrContractAddressCollision
case evmTypes.ExecutionErrCodeExecutionReverted:
return gethVM.ErrExecutionReverted
case evmTypes.ExecutionErrCodeMaxInitCodeSizeExceeded:
return gethVM.ErrMaxInitCodeSizeExceeded
case evmTypes.ExecutionErrCodeMaxCodeSizeExceeded:
return gethVM.ErrMaxCodeSizeExceeded
case evmTypes.ExecutionErrCodeInvalidJump:
return gethVM.ErrInvalidJump
case evmTypes.ExecutionErrCodeWriteProtection:
return gethVM.ErrWriteProtection
case evmTypes.ExecutionErrCodeReturnDataOutOfBounds:
return gethVM.ErrReturnDataOutOfBounds
case evmTypes.ExecutionErrCodeGasUintOverflow:
return gethVM.ErrGasUintOverflow
case evmTypes.ExecutionErrCodeInvalidCode:
return gethVM.ErrInvalidCode
case evmTypes.ExecutionErrCodeNonceUintOverflow:
return gethVM.ErrNonceUintOverflow
case evmTypes.ValidationErrCodeMisc:
return fmt.Errorf("validation error: %d", errorCode)
case evmTypes.ExecutionErrCodeMisc:
return fmt.Errorf("execution error: %d", errorCode)
}

return fmt.Errorf("unknown error code: %d", errorCode)
}
36 changes: 36 additions & 0 deletions tests/web3js/eth_deploy_contract_and_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,40 @@ it('deploy contract and interact', async() => {
)
}

// check that revert reason for custom error is correctly returned for gas estimation
Copy link
Contributor

Choose a reason for hiding this comment

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

lets create maybe gast estimation test separately, because it feels to me we will have multiple tests with weird cases

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You are right. It has become quite large, I must admit. I'll leave it for another PR though.

try {
let callCustomError = deployed.contract.methods.customError().encodeABI()
result = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: callCustomError,
gas: 1_000_000,
gasPrice: 0
})
} catch (error) {
assert.equal(error.innerError.message, 'execution reverted')
assert.equal(
error.innerError.data,
'0x9195785a00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001056616c756520697320746f6f206c6f7700000000000000000000000000000000'
)
}

// check that assertion error is correctly returned for gas estimation
try {
let callAssertError = deployed.contract.methods.assertError().encodeABI()
result = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: callAssertError,
gas: 1_000_000,
gasPrice: 0
})
} catch (error) {
assert.equal(error.innerError.message, 'execution reverted: Assert Error Message')
assert.equal(
error.innerError.data,
'0x08c379a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000014417373657274204572726f72204d657373616765000000000000000000000000'
)
}

}).timeout(10*1000)