diff --git a/.changeset/old-mirrors-doubt.md b/.changeset/old-mirrors-doubt.md new file mode 100644 index 0000000000000..3c960698b9836 --- /dev/null +++ b/.changeset/old-mirrors-doubt.md @@ -0,0 +1,6 @@ +--- +"@eth-optimism/integration-tests": patch +"@eth-optimism/l2geth": patch +--- + +Correctly set the OVM context based on the L1 values during `eth_call`. This will also set it during `eth_estimateGas`. Add tests for this in the integration tests diff --git a/integration-tests/test/ovmcontext.spec.ts b/integration-tests/test/ovmcontext.spec.ts index f6771e31b2d5d..1f633a5c487e3 100644 --- a/integration-tests/test/ovmcontext.spec.ts +++ b/integration-tests/test/ovmcontext.spec.ts @@ -99,6 +99,32 @@ describe('OVM Context: Layer 2 EVM Context', () => { } }) + it('should set correct OVM Context for `eth_call`', async () => { + const tip = await L2Provider.getBlockWithTransactions('latest') + const start = Math.max(0, tip.number - 5) + + for (let i = start; i < tip.number; i++) { + const block = await L2Provider.getBlockWithTransactions(i) + const [, returnData] = await OVMMulticall.callStatic.aggregate([ + [ + OVMMulticall.address, + OVMMulticall.interface.encodeFunctionData('getCurrentBlockTimestamp'), + ], + [ + OVMMulticall.address, + OVMMulticall.interface.encodeFunctionData('getCurrentBlockNumber'), + ], + ], {blockTag: i}) + + const timestamp = BigNumber.from(returnData[0]) + const blockNumber = BigNumber.from(returnData[1]) + const tx = block.transactions[0] as any + + expect(tx.l1BlockNumber).to.deep.equal(blockNumber.toNumber()) + expect(block.timestamp).to.deep.equal(timestamp.toNumber()) + } + }) + /** * `rollup_getInfo` is a new RPC endpoint that is used to return the OVM * context. The data returned should match what is actually being used as the @@ -126,8 +152,7 @@ describe('OVM Context: Layer 2 EVM Context', () => { const timestamp = BigNumber.from(returnData[0]) const blockNumber = BigNumber.from(returnData[1]) - // TODO: this is a bug and needs to be fixed - //expect(info.ethContext.blockNumber).to.deep.equal(blockNumber.toNumber()) + expect(info.ethContext.blockNumber).to.deep.equal(blockNumber.toNumber()) expect(info.ethContext.timestamp).to.deep.equal(timestamp.toNumber()) }) }) diff --git a/l2geth/core/state_transition_ovm.go b/l2geth/core/state_transition_ovm.go index 381fa3c3ecd6e..0f7b698d6b57a 100644 --- a/l2geth/core/state_transition_ovm.go +++ b/l2geth/core/state_transition_ovm.go @@ -103,7 +103,7 @@ func EncodeSimulatedMessage(msg Message, timestamp, blockNumber *big.Int, execut tx := ovmTransaction{ timestamp, - blockNumber, // TODO (what's the correct block number?) + blockNumber, uint8(msg.QueueOrigin().Uint64()), *msg.L1MessageSender(), *to, diff --git a/l2geth/internal/ethapi/api.go b/l2geth/internal/ethapi/api.go index 7b765cbe30bc7..9e19c59d3e89d 100644 --- a/l2geth/internal/ethapi/api.go +++ b/l2geth/internal/ethapi/api.go @@ -923,6 +923,9 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo data = []byte(*args.Data) } + blockNumber := header.Number + timestamp := new(big.Int).SetUint64(header.Time) + // Create new call message var msg core.Message msg = types.NewMessage(addr, args.To, 0, value, gas, gasPrice, data, false, &addr, nil, types.QueueOriginSequencer, 0) @@ -930,9 +933,19 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo cfg := b.ChainConfig() executionManager := cfg.StateDump.Accounts["OVM_ExecutionManager"] stateManager := cfg.StateDump.Accounts["OVM_StateManager"] - var err error - blockNumber := header.Number - timestamp := new(big.Int).SetUint64(header.Time) + block, err := b.BlockByNumber(ctx, rpc.BlockNumber(header.Number.Uint64())) + if err != nil { + return nil, 0, false, err + } + txs := block.Transactions() + if header.Number.Uint64() != 0 { + if len(txs) != 1 { + return nil, 0, false, fmt.Errorf("block %d has more than 1 transaction", header.Number.Uint64()) + } + tx := txs[0] + blockNumber = tx.L1BlockNumber() + timestamp = new(big.Int).SetUint64(tx.L1Timestamp()) + } msg, err = core.EncodeSimulatedMessage(msg, timestamp, blockNumber, executionManager, stateManager) if err != nil { return nil, 0, false, err @@ -968,6 +981,8 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo gp := new(core.GasPool).AddGas(math.MaxUint64) if vm.UsingOVM { evm.Context.EthCallSender = &addr + evm.Context.BlockNumber = blockNumber + evm.Context.Time = timestamp } res, gas, failed, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil {