diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index c2cf96533..5fd993f01 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -959,20 +959,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { ast.Walk(c, n.Fun) emit.Opcodes(c.prog.BinWriter, opcode.CALLA) case isSyscall(f): - if f.pkg.Name() == "runtime" && f.name == "Notify" { - tv := c.typeAndValueOf(n.Args[0]) - params := make([]string, 0, len(n.Args[1:])) - for _, p := range n.Args[1:] { - st, _ := c.scAndVMTypeFromExpr(p) - params = append(params, st.String()) - } - // Sometimes event name is stored in a var. - // Skip in this case. - if tv.Value != nil { - name := constant.StringVal(tv.Value) - c.emittedEvents[name] = append(c.emittedEvents[name], params) - } - } c.convertSyscall(f, n) default: emit.Call(c.prog.BinWriter, opcode.CALLL, f.label) diff --git a/pkg/compiler/compiler_test.go b/pkg/compiler/compiler_test.go index cfe300e8d..d77a26012 100644 --- a/pkg/compiler/compiler_test.go +++ b/pkg/compiler/compiler_test.go @@ -9,6 +9,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/compiler" "github.com/nspcc-dev/neo-go/pkg/config" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/stretchr/testify/require" ) @@ -130,3 +132,46 @@ func TestOnPayableChecks(t *testing.T) { require.Error(t, compileAndCheck(t, src)) }) } + +func TestEventWarnings(t *testing.T) { + src := `package payable + import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + func Main() { runtime.Notify("Event", 1) }` + + _, di, err := compiler.CompileWithDebugInfo("eventTest", strings.NewReader(src)) + require.NoError(t, err) + + t.Run("event it missing from config", func(t *testing.T) { + _, err = compiler.CreateManifest(di, &compiler.Options{}) + require.Error(t, err) + + t.Run("suppress", func(t *testing.T) { + _, err = compiler.CreateManifest(di, &compiler.Options{NoEventsCheck: true}) + require.NoError(t, err) + }) + }) + t.Run("wrong parameter number", func(t *testing.T) { + _, err = compiler.CreateManifest(di, &compiler.Options{ + ContractEvents: []manifest.Event{{Name: "Event"}}, + }) + require.Error(t, err) + }) + t.Run("wrong parameter type", func(t *testing.T) { + _, err = compiler.CreateManifest(di, &compiler.Options{ + ContractEvents: []manifest.Event{{ + Name: "Event", + Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.StringType)}, + }}, + }) + require.Error(t, err) + }) + t.Run("good", func(t *testing.T) { + _, err = compiler.CreateManifest(di, &compiler.Options{ + ContractEvents: []manifest.Event{{ + Name: "Event", + Parameters: []manifest.Parameter{manifest.NewParameter("number", smartcontract.IntegerType)}, + }}, + }) + require.NoError(t, err) + }) +} diff --git a/pkg/compiler/inline.go b/pkg/compiler/inline.go index d3653941b..7832b6c9d 100644 --- a/pkg/compiler/inline.go +++ b/pkg/compiler/inline.go @@ -2,6 +2,7 @@ package compiler import ( "go/ast" + "go/constant" "go/types" "github.com/nspcc-dev/neo-go/pkg/vm/emit" @@ -27,6 +28,8 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) { pkg := c.buildInfo.program.Package(f.pkg.Path()) sig := c.typeOf(n.Fun).(*types.Signature) + c.processNotify(f, n.Args) + // When inlined call is used during global initialization // there is no func scope, thus this if. if c.scope == nil { @@ -114,3 +117,23 @@ func (c *codegen) inlineCall(f *funcScope, n *ast.CallExpr) { c.importMap = oldMap c.pkgInfoInline = c.pkgInfoInline[:len(c.pkgInfoInline)-1] } + +func (c *codegen) processNotify(f *funcScope, args []ast.Expr) { + if f != nil && f.pkg.Path() == interopPrefix+"/runtime" && f.name == "Notify" { + // Sometimes event name is stored in a var. + // Skip in this case. + tv := c.typeAndValueOf(args[0]) + if tv.Value == nil { + return + } + + params := make([]string, 0, len(args[1:])) + for _, p := range args[1:] { + st, _ := c.scAndVMTypeFromExpr(p) + params = append(params, st.String()) + } + + name := constant.StringVal(tv.Value) + c.emittedEvents[name] = append(c.emittedEvents[name], params) + } +}