Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 85aa5fa
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 24 05:57:39 2025 +0100

    lint: add rule to disallow `new Error` throwing

commit 1e97567
Merge: a8cd9e1 bd77a74
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 24 05:44:30 2025 +0100

    Merge branch 'master' into evm-error-handling

commit a8cd9e1
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 24 05:44:21 2025 +0100

    util: introduce new temp error with unset error code

commit aa3702b
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 10 16:04:41 2025 +0100

    vm/client: fix build

commit 16d1b38
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 10 15:40:57 2025 +0100

    evm/util: update to new, simpler error format

commit ec01f1b
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 10 14:37:24 2025 +0100

    util: update base error class

commit 70b2df5
Merge: 293f4cc 1774df6
Author: Jochem Brouwer <[email protected]>
Date:   Mon Feb 10 14:22:35 2025 +0100

    Merge branch 'master' into evm-error-handling

commit 293f4cc
Merge: b4458d7 99cfdd6
Author: Jochem Brouwer <[email protected]>
Date:   Tue Jan 14 03:04:15 2025 +0100

    Merge branch 'master' into evm-error-handling

commit b4458d7
Merge: 71e77dc 100d77d
Author: Jochem Brouwer <[email protected]>
Date:   Fri Dec 13 17:50:26 2024 +0100

    Merge branch 'master' into evm-error-handling

commit 71e77dc
Author: Jochem Brouwer <[email protected]>
Date:   Tue Oct 1 13:57:38 2024 +0200

    evm: fix err handling

commit d00b7bf
Author: Jochem Brouwer <[email protected]>
Date:   Tue Oct 1 13:46:08 2024 +0200

    evm/util: error overhaul
  • Loading branch information
jochem-brouwer committed Feb 24, 2025
1 parent 8585be6 commit 58c9057
Show file tree
Hide file tree
Showing 26 changed files with 627 additions and 184 deletions.
2 changes: 1 addition & 1 deletion packages/client/src/rpc/modules/eth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ export class Eth {
throw {
code: 3,
data: bytesToHex(execResult.returnValue),
message: execResult.exceptionError.error,
message: execResult.exceptionError.type.code,
}
}
return bytesToHex(execResult.returnValue)
Expand Down
27 changes: 17 additions & 10 deletions packages/evm/src/exceptions.ts → packages/evm/src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
export enum ERROR {
import { EthereumJSError } from '@ethereumjs/util'

import type { EOFError } from './eof/errors.js'

// TODO: merge EOF errors in here
export enum EVMErrorCode {
OUT_OF_GAS = 'out of gas',
CODESTORE_OUT_OF_GAS = 'code store out of gas',
CODESIZE_EXCEEDS_MAXIMUM = 'code size to deposit exceeds maximum code size',
Expand All @@ -15,13 +20,11 @@ export enum ERROR {
REFUND_EXHAUSTED = 'refund exhausted',
VALUE_OVERFLOW = 'value overflow',
INSUFFICIENT_BALANCE = 'insufficient balance',
INVALID_BEGINSUB = 'invalid BEGINSUB',
INVALID_RETURNSUB = 'invalid RETURNSUB',
INVALID_JUMPSUB = 'invalid JUMPSUB',
INVALID_BYTECODE_RESULT = 'invalid bytecode deployed',
INITCODE_SIZE_VIOLATION = 'initcode exceeds max initcode size',
INVALID_INPUT_LENGTH = 'invalid input length',
INVALID_EOF_FORMAT = 'invalid EOF format',
INVALID_PRECOMPILE = 'invalid precompile',

// BLS errors
BLS_12_381_INVALID_INPUT_LENGTH = 'invalid input length',
Expand All @@ -38,12 +41,16 @@ export enum ERROR {
INVALID_PROOF = 'kzg proof invalid',
}

export class EvmError {
error: ERROR
errorType: string
type EVMErrorType =
| {
code: EVMErrorCode | EOFError
}
| { code: EVMErrorCode.REVERT; revertBytes: Uint8Array }

constructor(error: ERROR) {
this.error = error
this.errorType = 'EvmError'
export class EVMError extends EthereumJSError<EVMErrorType> {
constructor(type: EVMErrorType, message?: string) {
super(type, message)
}

// TODO: add helper method to format the error in a human readable way
}
60 changes: 43 additions & 17 deletions packages/evm/src/evm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
KECCAK256_NULL,
KECCAK256_RLP,
MAX_INTEGER,
UsageError,
UsageErrorType,
bigIntToBytes,
bytesToUnprefixedHex,
createZeroAddress,
Expand All @@ -22,7 +24,7 @@ import { EventEmitter } from 'eventemitter3'

import { FORMAT } from './eof/constants.js'
import { isEOF } from './eof/util.js'
import { ERROR, EvmError } from './exceptions.js'
import { EVMError, EVMErrorCode } from './errors.js'
import { Interpreter } from './interpreter.js'
import { Journal } from './journal.js'
import { EVMPerformanceLogger } from './logger.js'
Expand Down Expand Up @@ -443,7 +445,9 @@ export class EVM implements EVMInterface {
createdAddress: message.to,
execResult: {
returnValue: new Uint8Array(0),
exceptionError: new EvmError(ERROR.INITCODE_SIZE_VIOLATION),
exceptionError: new EVMError({
code: EVMErrorCode.INITCODE_SIZE_VIOLATION,
}),
executionGasUsed: message.gasLimit,
},
}
Expand Down Expand Up @@ -502,7 +506,9 @@ export class EVM implements EVMInterface {
createdAddress: message.to,
execResult: {
returnValue: new Uint8Array(0),
exceptionError: new EvmError(ERROR.CREATE_COLLISION),
exceptionError: new EVMError({
code: EVMErrorCode.CREATE_COLLISION,
}),
executionGasUsed: message.gasLimit,
},
}
Expand Down Expand Up @@ -803,8 +809,8 @@ export class EVM implements EVMInterface {
let gasUsed = message.gasLimit - interpreterRes.runState!.gasLeft
if (interpreterRes.exceptionError) {
if (
interpreterRes.exceptionError.error !== ERROR.REVERT &&
interpreterRes.exceptionError.error !== ERROR.INVALID_EOF_FORMAT
interpreterRes.exceptionError.type.code !== EVMErrorCode.REVERT &&
interpreterRes.exceptionError.type.code !== EVMErrorCode.INVALID_EOF_FORMAT
) {
gasUsed = message.gasLimit
}
Expand Down Expand Up @@ -941,7 +947,7 @@ export class EVM implements EVMInterface {
const { executionGasUsed, exceptionError, returnValue } = result.execResult
debug(
`Received message execResult: [ gasUsed=${executionGasUsed} exceptionError=${
exceptionError ? `'${exceptionError.error}'` : 'none'
exceptionError ? `'${exceptionError.type.code}'` : 'none'
} returnValue=${short(returnValue)} gasRefund=${result.execResult.gasRefund ?? 0} ]`,
)
}
Expand All @@ -951,14 +957,17 @@ export class EVM implements EVMInterface {
// There is one exception: if the CODESTORE_OUT_OF_GAS error is thrown
// (this only happens the Frontier/Chainstart fork)
// then the error is dismissed
if (err && err.error !== ERROR.CODESTORE_OUT_OF_GAS) {
if (err && err.type.code !== EVMErrorCode.CODESTORE_OUT_OF_GAS) {
result.execResult.selfdestruct = new Set()
result.execResult.createdAddresses = new Set()
result.execResult.gasRefund = BIGINT_0
}
if (
err &&
!(this.common.hardfork() === Hardfork.Chainstart && err.error === ERROR.CODESTORE_OUT_OF_GAS)
!(
this.common.hardfork() === Hardfork.Chainstart &&
err.type.code === EVMErrorCode.CODESTORE_OUT_OF_GAS
)
) {
result.execResult.logs = []
await this.journal.revert()
Expand Down Expand Up @@ -1028,7 +1037,9 @@ export class EVM implements EVMInterface {
gasLimit: bigint,
): Promise<ExecResult> | ExecResult {
if (typeof code !== 'function') {
throw EthereumJSErrorUnsetCode('Invalid precompile')
throw new EVMError({
code: EVMErrorCode.INVALID_PRECOMPILE,
})
}

const opts = {
Expand Down Expand Up @@ -1088,7 +1099,9 @@ export class EVM implements EVMInterface {
protected async _reduceSenderBalance(account: Account, message: Message): Promise<void> {
account.balance -= message.value
if (account.balance < BIGINT_0) {
throw new EvmError(ERROR.INSUFFICIENT_BALANCE)
throw new EVMError({
code: EVMErrorCode.INSUFFICIENT_BALANCE,
})
}
const result = this.journal.putAccount(message.caller, account)
if (this.DEBUG) {
Expand All @@ -1100,7 +1113,9 @@ export class EVM implements EVMInterface {
protected async _addToBalance(toAccount: Account, message: MessageWithTo): Promise<void> {
const newBalance = toAccount.balance + message.value
if (newBalance > MAX_INTEGER) {
throw new EvmError(ERROR.VALUE_OVERFLOW)
throw new EVMError({
code: EVMErrorCode.VALUE_OVERFLOW,
})
}
toAccount.balance = newBalance
// putAccount as the nonce may have changed for contract creation
Expand Down Expand Up @@ -1148,47 +1163,58 @@ export class EVM implements EVMInterface {
}
}

// TODO clean me up
export function OOGResult(gasLimit: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasLimit,
exceptionError: new EvmError(ERROR.OUT_OF_GAS),
exceptionError: new EVMError({
code: EVMErrorCode.OUT_OF_GAS,
}),
}
}
// CodeDeposit OOG Result
export function COOGResult(gasUsedCreateCode: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsedCreateCode,
exceptionError: new EvmError(ERROR.CODESTORE_OUT_OF_GAS),
exceptionError: new EVMError({
code: EVMErrorCode.OUT_OF_GAS,
}),
}
}

export function INVALID_BYTECODE_RESULT(gasLimit: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasLimit,
exceptionError: new EvmError(ERROR.INVALID_BYTECODE_RESULT),
exceptionError: new EVMError({
code: EVMErrorCode.INVALID_BYTECODE_RESULT,
}),
}
}

export function INVALID_EOF_RESULT(gasLimit: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasLimit,
exceptionError: new EvmError(ERROR.INVALID_EOF_FORMAT),
exceptionError: new EVMError({
code: EVMErrorCode.INVALID_EOF_FORMAT,
}),
}
}

export function CodesizeExceedsMaximumError(gasUsed: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsed,
exceptionError: new EvmError(ERROR.CODESIZE_EXCEEDS_MAXIMUM),
exceptionError: new EVMError({
code: EVMErrorCode.CODESIZE_EXCEEDS_MAXIMUM,
}),
}
}

export function EvmErrorResult(error: EvmError, gasUsed: bigint): ExecResult {
export function EvmErrorResult(error: EVMError, gasUsed: bigint): ExecResult {
return {
returnValue: new Uint8Array(0),
executionGasUsed: gasUsed,
Expand Down
6 changes: 3 additions & 3 deletions packages/evm/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EOFContainer, validateEOF } from './eof/container.js'
import { EVMError, EVMErrorCode } from './errors.js'
import { EVM } from './evm.js'
import { ERROR as EVMErrorMessage, EvmError } from './exceptions.js'
import { Message } from './message.js'
import { getOpcodesForHF } from './opcodes/index.js'
import {
Expand Down Expand Up @@ -46,8 +46,8 @@ export type {
export {
EOFContainer,
EVM,
EvmError,
EVMErrorMessage,
EVMError,
EVMErrorCode,
EVMMockBlockchain,
getActivePrecompiles,
getOpcodesForHF,
Expand Down
Loading

0 comments on commit 58c9057

Please sign in to comment.