diff --git a/lib/evm/evm.ts b/lib/evm/evm.ts index 9d786e84a67..b9a7fa1c875 100644 --- a/lib/evm/evm.ts +++ b/lib/evm/evm.ts @@ -108,6 +108,7 @@ export default class EVM { _targetMessage: Message | undefined _targetMessageResult: EVMResult | undefined _accountMessageResult: EVMResult | undefined + _lastOvmREVERTData: Buffer | undefined constructor(vm: any, txContext: TxContext, block: any) { this._vm = vm @@ -144,6 +145,11 @@ export default class EVM { this._targetMessage = message } + if (message.isCallToOvmREVERT()) { + // slice off 4 bytes methodId + 64 bytes abi encode --> gets the raw data passed in + this._lastOvmREVERTData = message.data.slice(68) + } + let result if (message.to) { const code = await this._state.getContractCode(message.to) @@ -199,8 +205,6 @@ export default class EVM { returnData = returnData.slice(160) } - result.execResult.exceptionError - const EOAReturnedFalse = this._accountMessageResult?.execResult.returnValue.slice(0, 32).toString('hex') == '00'.repeat(32) @@ -210,6 +214,12 @@ export default class EVM { ? new VmError(ERROR.REVERT) : this._targetMessageResult.execResult.exceptionError + // The OVM does not allow for EVM creation messages that revert. + // We can recover the initcode's intended revert data by checking the last call to ovmREVERT. + if (wasDeployException && !!this._lastOvmREVERTData) { + returnData = this._lastOvmREVERTData + } + result = { ...result, createdAddress: this._targetMessageResult.createdAddress, diff --git a/lib/evm/message.ts b/lib/evm/message.ts index dbf6a62a291..5991683081b 100644 --- a/lib/evm/message.ts +++ b/lib/evm/message.ts @@ -6,6 +6,8 @@ import VM from '../index' import { toHexString, fromHexString } from '../ovm/utils/buffer-utils' import { NULL_ADDRESS } from '../ovm/utils/constants' +const ovmREVERTMethodId = Buffer.from('2a2a7adb', 'hex') + export default class Message { to: Buffer value: BN @@ -54,6 +56,10 @@ export default class Message { ) } + isCallToOvmREVERT(): boolean { + return this.data.slice(0, 4).equals(ovmREVERTMethodId) + } + toOvmMessage(vm: VM, block: any): Message { if (!vm.contracts.OVM_ExecutionManager.address) { throw new Error('Cannot create a message because the ExecutionManager does not exist.')