diff --git a/arbitrator/prover/test-cases/user.wat b/arbitrator/prover/test-cases/user.wat index 9ecb4dcc45..68f45a610a 100644 --- a/arbitrator/prover/test-cases/user.wat +++ b/arbitrator/prover/test-cases/user.wat @@ -22,6 +22,12 @@ i32.const 0xFFFFFF i32.load ) + (func $infinite_loop (result i32) + (loop $loop + br $loop + ) + i32.const 0 + ) (func (export "user_entrypoint") (param $args_len i32) (result i32) ;; this func uses $args_len to select which func to call @@ -43,6 +49,12 @@ (then (call $out_of_bounds) (return)) ) + ;; reverts due to an out-of-gas error + (i32.eq (local.get $args_len) (i32.const 4)) + (if + (then (call $infinite_loop) (return)) + ) + (i32.eq (local.get $args_len) (i32.const 32)) (if (then (call $storage_load) (return)) diff --git a/system_tests/program_test.go b/system_tests/program_test.go index ea4ccddd03..94aaef5f34 100644 --- a/system_tests/program_test.go +++ b/system_tests/program_test.go @@ -1005,6 +1005,31 @@ func TestProgramMemory(t *testing.T) { testMemory(t, true) } +func TestProgramInfiniteLoopShouldCauseErrOutOfGas(t *testing.T) { + t.Parallel() + testInfiniteLoopCausesErrOutOfGas(t, true) + testInfiniteLoopCausesErrOutOfGas(t, false) +} + +func testInfiniteLoopCausesErrOutOfGas(t *testing.T, jit bool) { + builder, auth, cleanup := setupProgramTest(t, jit) + ctx := builder.ctx + l2info := builder.L2Info + l2client := builder.L2.Client + defer cleanup() + + userWasm := deployWasm(t, ctx, auth, l2client, "../arbitrator/prover/test-cases/user.wat") + // Passing input of size 4 invokes $infinite_loop function that calls the infinite loop + tx := l2info.PrepareTxTo("Owner", &userWasm, 1000000, nil, make([]byte, 4)) + Require(t, l2client.SendTransaction(ctx, tx)) + receipt, err := EnsureTxSucceeded(ctx, l2client, tx) + if !strings.Contains(err.Error(), vm.ErrOutOfGas.Error()) { + t.Fatalf("transaction should have failed with out of gas error but instead failed with: %v", err) + } + + validateBlocks(t, receipt.BlockNumber.Uint64(), jit, builder) +} + func testMemory(t *testing.T, jit bool) { builder, auth, cleanup := setupProgramTest(t, jit) ctx := builder.ctx