-
Notifications
You must be signed in to change notification settings - Fork 790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EVM: error handling #3714
base: master
Are you sure you want to change the base?
EVM: error handling #3714
Conversation
Okay 👍 |
packages/evm/src/errors.ts
Outdated
type EvmRuntimeErrorType = { | ||
code: EvmErrorCode.RUNTIME_ERROR | ||
reason: RuntimeErrorMessage | EOFError | ||
} & ( | ||
| { reason: RuntimeErrorMessage.REVERT; revertBytes: Uint8Array } | ||
| { reason: Exclude<RuntimeErrorMessage, RuntimeErrorMessage.REVERT> | EOFError } | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this scalable? I'm wondering how this would look if we had multiple error codes with corresponding different formats. Right now we're just having one case for "RuntimeErrorMessage.REVERT" and another excluding "RuntimeErrorMessage.REVERT", but I wonder if that might become too burdensome if we need to exclude more
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was some experimenting with the typescript typing I did. It ensures that if reason
is RuntimeErrorMessage.REVERT
it has the mandatory revertBytes
. If is NOT a REVERT
then the reason could be any of the RuntimeErrorMessage
or an EOFError.
Note: EOFError has not been migrated to the EvmError, likely when I do that this typing (the second line) does not have to be there (will check)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This typing (I checked) is just to type the evm errors such that the REVERT error has a revertBytes
field. It is straightforward to add new error codes or new error reasons, or the inject specific error which adds context (like the mandatory revertBytes
field in the REVERT
error)
packages/evm/src/errors.ts
Outdated
constructor(error: ERROR) { | ||
this.error = error | ||
this.errorType = 'EvmError' | ||
export class EvmError extends EthereumJSError<EvmErrorType> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note, but I think we might want to migrate to the EVM (rather than Evm) capitalization as we've done for some others (Json -> JSON, etc.)
I like the approach, as it has the obvious benefits of:
Some of the things that I'm questioning however:
Do you have some examples on how Lodestar handles custom error codes in similar contexts (multiple error codes within a single package, with different types for each of them?). I'Ve looked but can only find examples like this: https://github.com/ChainSafe/lodestar/blob/dad9037e7739d5bcbccfe627e715ef40e9ba935b/packages/api/src/utils/server/error.ts which are simpler than what we do. Nice work! |
For performance, this should not have any noticeable impact, the errors are just "nicer" now since it gives error codes and error context (as example here in the REVERT error). I will clean up this PR to reflect how this would work, and if all is fine we can roll this all repo-wide. |
Great! Looking at Lodestar's handling I think it looks super clean, for e.g. this type is really readable and it would be easy to add new error types etc. : https://github.com/ChainSafe/lodestar/blob/unstable/packages/beacon-node/src/chain/errors/blockError.ts#L74 Let me know once this is ready for an actual review, excited about rolling this out progressively throughout the monorepo! |
ee33f56
to
293f4cc
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more. |
Part of #3712
Excerpt from
evm/errors.ts
:This is a Proof-of-Concept (I still need to do some cycles to clean this up though) which shows that we now have two EVM error types: a
UNSUPPORTED_FEATURE
or aRUNTIME_ERROR
. In case of aRUNTIME_ERROR
, typescript now demands areason
field in the error (this could for instance be "stack overflow", "stack underflow", etc.What is nice: for the
REVERT
reason it demands arevertBytes
field, which is actually the reverted bytes in case the EVM runs into a revert (from these bytes error messages can be derived, such as solidity revert strings!).Errors now look like this:
(I had added the
error.code
field but I think we should keep it aterror.type.code
).The error handler (taken / inspired from lodestar: https://github.com/ChainSafe/lodestar/blob/unstable/packages/utils/src/errors.ts) allows to add custom error classes (see
EvmError
class in this case, can add extra constructor arguments for environment situation), and also has amessage
argument which allows for custom message strings.Note: super WIP. I am not completely satisfied yet with the results, because now EVM has a huge code bloat due to instantiating these error messages. I have to find a way to go back to the "old versions" (
trap(ERROR.OUT_OF_GAS)
) but still remaining type-safety (for the REVERT error string for instance).Note, tests will likely fail because of the updated error format.