package standard import ( "errors" "testing" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/stretchr/testify/require" ) func fooMethodBarEvent() *manifest.Manifest { return &manifest.Manifest{ ABI: manifest.ABI{ Methods: []manifest.Method{ { Name: "foo", Parameters: []manifest.Parameter{ {Type: smartcontract.ByteArrayType}, {Type: smartcontract.PublicKeyType}, }, ReturnType: smartcontract.IntegerType, Safe: true, }, }, Events: []manifest.Event{ { Name: "bar", Parameters: []manifest.Parameter{ {Type: smartcontract.StringType}, }, }, }, }, } } func TestComplyMissingMethod(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Name = "notafoo" err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrMethodMissing)) } func TestComplyInvalidReturnType(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).ReturnType = smartcontract.VoidType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrInvalidReturnType)) } func TestComplyMethodParameterCount(t *testing.T) { t.Run("Method", func(t *testing.T) { m := fooMethodBarEvent() f := m.ABI.GetMethod("foo", -1) f.Parameters = append(f.Parameters, manifest.Parameter{Type: smartcontract.BoolType}) err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrMethodMissing)) }) t.Run("Event", func(t *testing.T) { m := fooMethodBarEvent() ev := m.ABI.GetEvent("bar") ev.Parameters = append(ev.Parameters[:0]) err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrInvalidParameterCount)) }) } func TestComplyParameterType(t *testing.T) { t.Run("Method", func(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Parameters[0].Type = smartcontract.InteropInterfaceType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrInvalidParameterType)) }) t.Run("Event", func(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetEvent("bar").Parameters[0].Type = smartcontract.InteropInterfaceType err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrInvalidParameterType)) }) } func TestComplyParameterName(t *testing.T) { t.Run("Method", func(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Parameters[0].Name = "hehe" s := &Standard{Manifest: *fooMethodBarEvent()} err := Comply(m, s) require.True(t, errors.Is(err, ErrInvalidParameterName)) require.NoError(t, ComplyABI(m, s)) }) t.Run("Event", func(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetEvent("bar").Parameters[0].Name = "hehe" s := &Standard{Manifest: *fooMethodBarEvent()} err := Comply(m, s) require.True(t, errors.Is(err, ErrInvalidParameterName)) require.NoError(t, ComplyABI(m, s)) }) } func TestMissingEvent(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetEvent("bar").Name = "notabar" err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrEventMissing)) } func TestSafeFlag(t *testing.T) { m := fooMethodBarEvent() m.ABI.GetMethod("foo", -1).Safe = false err := Comply(m, &Standard{Manifest: *fooMethodBarEvent()}) require.True(t, errors.Is(err, ErrSafeMethodMismatch)) } func TestComplyValid(t *testing.T) { m := fooMethodBarEvent() m.ABI.Methods = append(m.ABI.Methods, manifest.Method{ Name: "newmethod", Offset: 123, ReturnType: smartcontract.ByteArrayType, }) m.ABI.Events = append(m.ABI.Events, manifest.Event{ Name: "otherevent", Parameters: []manifest.Parameter{{ Name: "names do not matter", Type: smartcontract.IntegerType, }}, }) require.NoError(t, Comply(m, &Standard{Manifest: *fooMethodBarEvent()})) } func TestCheck(t *testing.T) { m := manifest.NewManifest("Test") require.Error(t, Check(m, manifest.NEP17StandardName)) m.ABI.Methods = append(m.ABI.Methods, decimalTokenBase.ABI.Methods...) m.ABI.Methods = append(m.ABI.Methods, nep17.ABI.Methods...) m.ABI.Events = append(m.ABI.Events, nep17.ABI.Events...) require.NoError(t, Check(m, manifest.NEP17StandardName)) require.NoError(t, CheckABI(m, manifest.NEP17StandardName)) } func TestOptional(t *testing.T) { var m Standard m.Optional = []manifest.Method{{ Name: "optMet", Parameters: []manifest.Parameter{{Type: smartcontract.ByteArrayType}}, ReturnType: smartcontract.IntegerType, }} t.Run("wrong parameter count, do not check", func(t *testing.T) { var actual manifest.Manifest actual.ABI.Methods = []manifest.Method{{ Name: "optMet", ReturnType: smartcontract.IntegerType, }} require.NoError(t, Comply(&actual, &m)) }) t.Run("good parameter count, bad return", func(t *testing.T) { var actual manifest.Manifest actual.ABI.Methods = []manifest.Method{{ Name: "optMet", Parameters: []manifest.Parameter{{Type: smartcontract.ArrayType}}, ReturnType: smartcontract.IntegerType, }} require.Error(t, Comply(&actual, &m)) }) t.Run("good parameter count, good return", func(t *testing.T) { var actual manifest.Manifest actual.ABI.Methods = []manifest.Method{{ Name: "optMet", Parameters: []manifest.Parameter{{Type: smartcontract.ByteArrayType}}, ReturnType: smartcontract.IntegerType, }} require.NoError(t, Comply(&actual, &m)) }) }