Skip to content

Commit

Permalink
fix: static state change error (#4499)
Browse files Browse the repository at this point in the history
Co-authored-by: Franco Victorio <[email protected]>
  • Loading branch information
Wodann and fvictorio committed Oct 20, 2023
1 parent 22b5e1f commit 0680887
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export class EdrMiner implements BlockMinerAdapter {
});
}
} else if ("executionResult" in traceItem) {
await vmTracer.addAfterMessage(traceItem);
await vmTracer.addAfterMessage(traceItem.executionResult);
} else {
await vmTracer.addBeforeMessage(traceItem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,8 @@ export function edrResultToEthereumjsEvmResult(
}

export function ethereumjsEvmResultToEdrResult(
result: EVMResult
result: EVMResult,
overrideExceptionalHalt: boolean = false
): ExecutionResult {
const gasUsed = result.execResult.executionGasUsed;

Expand Down Expand Up @@ -589,16 +590,35 @@ export function ethereumjsEvmResultToEdrResult(
},
};
} else {
const vmError = Exit.fromEthereumJSEvmError(
result.execResult.exceptionError
);

return {
result: {
reason: vmError.getEdrExceptionalHalt(),
if (overrideExceptionalHalt) {
const overridenResult: any = {
gasUsed,
},
};
};

// Throw an error if reason is accessed
Object.defineProperty(overridenResult, "reason", {
get: () => {
throw new Error(
"Cannot access reason of an exceptional halt in EthereumJS mode"
);
},
});

return {
result: overridenResult,
};
} else {
const vmError = Exit.fromEthereumJSEvmError(
result.execResult.exceptionError
);

return {
result: {
reason: vmError.getEdrExceptionalHalt(),
gasUsed,
},
};
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class EdrBlockBuilder implements BlockBuilderAdapter {
if ("pc" in traceItem) {
await this._vmTracer.addStep(traceItem);
} else if ("executionResult" in traceItem) {
await this._vmTracer.addAfterMessage(traceItem);
await this._vmTracer.addAfterMessage(traceItem.executionResult);
} else {
await this._vmTracer.addBeforeMessage(traceItem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,11 @@ export class EdrAdapter implements VMAdapter {
const trace = edrResult.trace!;
for (const traceItem of trace) {
if ("pc" in traceItem) {
// TODO: these "as any" shouldn't be necessary, we had
// to add them after merging the changes in main
await this._vmTracer.addStep(traceItem as any);
await this._vmTracer.addStep(traceItem);
} else if ("executionResult" in traceItem) {
await this._vmTracer.addAfterMessage(traceItem as any);
await this._vmTracer.addAfterMessage(traceItem.executionResult);
} else {
await this._vmTracer.addBeforeMessage(traceItem as any);
await this._vmTracer.addBeforeMessage(traceItem);
}
}

Expand Down Expand Up @@ -504,7 +502,7 @@ export class EdrAdapter implements VMAdapter {
if ("pc" in traceItem) {
await this._vmTracer.addStep(traceItem);
} else if ("executionResult" in traceItem) {
await this._vmTracer.addAfterMessage(traceItem);
await this._vmTracer.addAfterMessage(traceItem.executionResult);
} else {
await this._vmTracer.addBeforeMessage(traceItem);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
InterpreterStep,
Message,
} from "@nomicfoundation/ethereumjs-evm";
import { ERROR } from "@nomicfoundation/ethereumjs-evm/dist/exceptions";
import {
DefaultStateManager,
StateManager,
Expand Down Expand Up @@ -767,11 +768,21 @@ export class EthereumJSAdapter implements VMAdapter {
next: any
): Promise<void> {
try {
const executionResult = ethereumjsEvmResultToEdrResult(result);
const hasExceptionalHalt =
result.execResult.exceptionError !== undefined &&
result.execResult.exceptionError.error !== ERROR.REVERT;

await this._vmTracer.addAfterMessage({
const executionResult = ethereumjsEvmResultToEdrResult(
result,
hasExceptionalHalt
);

await this._vmTracer.addAfterMessage(
executionResult,
});
hasExceptionalHalt
? Exit.fromEthereumJSEvmError(result.execResult.exceptionError)
: undefined
);

for (const listener of this._afterMessageListeners) {
await listener(result);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export enum ExitCode {
STACK_UNDERFLOW,
CODESIZE_EXCEEDS_MAXIMUM,
CREATE_COLLISION,
STATIC_STATE_CHANGE,
}

export class Exit {
Expand All @@ -20,8 +21,9 @@ export class Exit {
case SuccessReason.Return:
case SuccessReason.SelfDestruct:
return new Exit(ExitCode.SUCCESS);
// TODO: Should we throw an error if default is hit?
}

const _exhaustiveCheck: never = reason;
}

public static fromEdrExceptionalHalt(halt: ExceptionalHalt): Exit {
Expand All @@ -45,9 +47,8 @@ export class Exit {
return new Exit(ExitCode.CODESIZE_EXCEEDS_MAXIMUM);

default: {
// TODO temporary, should be removed in production
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
throw new Error(`Unmatched edr exceptional halt: ${halt}`);
throw new Error(`Unmatched EDR exceptional halt: ${halt}`);
}
}
}
Expand Down Expand Up @@ -85,6 +86,10 @@ export class Exit {
return new Exit(ExitCode.CREATE_COLLISION);
}

if (evmError.error === ERROR.STATIC_STATE_CHANGE) {
return new Exit(ExitCode.STATIC_STATE_CHANGE);
}

// TODO temporary, should be removed in production
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
throw new Error(`Unmatched evm error: ${evmError.error}`);
Expand Down Expand Up @@ -114,6 +119,8 @@ export class Exit {
return "Codesize exceeds maximum";
case ExitCode.CREATE_COLLISION:
return "Create collision";
case ExitCode.STATIC_STATE_CHANGE:
return "Static state change";
}

const _exhaustiveCheck: never = this.kind;
Expand All @@ -137,6 +144,8 @@ export class Exit {
return new EvmError(ERROR.CODESIZE_EXCEEDS_MAXIMUM);
case ExitCode.CREATE_COLLISION:
return new EvmError(ERROR.CREATE_COLLISION);
case ExitCode.STATIC_STATE_CHANGE:
return new EvmError(ERROR.STATIC_STATE_CHANGE);
}

const _exhaustiveCheck: never = this.kind;
Expand All @@ -155,7 +164,7 @@ export class Exit {

default:
// eslint-disable-next-line @nomicfoundation/hardhat-internal-rules/only-hardhat-error
throw new Error(`Unmatched edr exceptional halt: ${this.kind}`);
throw new Error(`Unmatched exit code: ${this.kind}`);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { Common } from "@nomicfoundation/ethereumjs-common";
import {
CreateOutput,
ExecutionResult,
TracingMessage,
TracingMessageResult,
TracingStep,
} from "@ignored/edr";

Expand All @@ -29,9 +29,7 @@ const DUMMY_RETURN_DATA = Buffer.from([]);
const DUMMY_GAS_USED = 0n;

export class VMTracer {
public tracingMessages: TracingMessage[] = [];
public tracingSteps: TracingStep[] = [];
public tracingMessageResults: TracingMessageResult[] = [];

private _messageTraces: MessageTrace[] = [];
private _lastError: Error | undefined;
Expand Down Expand Up @@ -67,13 +65,9 @@ export class VMTracer {

if (message.depth === 0) {
this._messageTraces = [];
this.tracingMessages = [];
this.tracingSteps = [];
this.tracingMessageResults = [];
}

this.tracingMessages.push(message);

if (message.to === undefined) {
const createTrace: CreateMessageTrace = {
code: message.data,
Expand Down Expand Up @@ -184,18 +178,16 @@ export class VMTracer {
}
}

public async addAfterMessage(result: TracingMessageResult) {
public async addAfterMessage(result: ExecutionResult, haltOverride?: Exit) {
if (!this._shouldKeepTracing()) {
return;
}

this.tracingMessageResults.push(result);

try {
const trace = this._messageTraces[this._messageTraces.length - 1];
trace.gasUsed = result.executionResult.result.gasUsed;
trace.gasUsed = result.result.gasUsed;

const executionResult = result.executionResult.result;
const executionResult = result.result;
if (isSuccessResult(executionResult)) {
trace.exit = Exit.fromEdrSuccessReason(executionResult.reason);
trace.returnData = executionResult.output.returnValue;
Expand All @@ -206,10 +198,13 @@ export class VMTracer {
).address;
}
} else if (isHaltResult(executionResult)) {
trace.exit = Exit.fromEdrExceptionalHalt(executionResult.reason);
trace.exit =
haltOverride ?? Exit.fromEdrExceptionalHalt(executionResult.reason);

trace.returnData = Buffer.from([]);
} else {
trace.exit = new Exit(ExitCode.REVERT);

trace.returnData = executionResult.output;
}

Expand Down

0 comments on commit 0680887

Please sign in to comment.