diff --git a/pkg/smartcontract/manifest/abi.go b/pkg/smartcontract/manifest/abi.go new file mode 100644 index 000000000..7a83893d5 --- /dev/null +++ b/pkg/smartcontract/manifest/abi.go @@ -0,0 +1,102 @@ +package manifest + +import ( + "errors" + + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" +) + +const ( + // MethodInit is a name for default initialization method. + MethodInit = "_initialize" + + // MethodDeploy is a name for default method called during contract deployment. + MethodDeploy = "_deploy" + + // MethodVerify is a name for default verification method. + MethodVerify = "verify" + + // MethodOnNEP17Payment is name of the method which is called when contract receives NEP-17 tokens. + MethodOnNEP17Payment = "onNEP17Payment" + + // MethodOnNEP11Payment is the name of the method which is called when contract receives NEP-11 tokens. + MethodOnNEP11Payment = "onNEP11Payment" +) + +// ABI represents a contract application binary interface. +type ABI struct { + Methods []Method `json:"methods"` + Events []Event `json:"events"` +} + +// GetMethod returns methods with the specified name. +func (a *ABI) GetMethod(name string, paramCount int) *Method { + for i := range a.Methods { + if a.Methods[i].Name == name && (paramCount == -1 || len(a.Methods[i].Parameters) == paramCount) { + return &a.Methods[i] + } + } + return nil +} + +// GetEvent returns event with the specified name. +func (a *ABI) GetEvent(name string) *Event { + for i := range a.Events { + if a.Events[i].Name == name { + return &a.Events[i] + } + } + return nil +} + +// ToStackItem converts ABI to stackitem.Item. +func (a *ABI) ToStackItem() stackitem.Item { + methods := make([]stackitem.Item, len(a.Methods)) + for i := range a.Methods { + methods[i] = a.Methods[i].ToStackItem() + } + events := make([]stackitem.Item, len(a.Events)) + for i := range a.Events { + events[i] = a.Events[i].ToStackItem() + } + return stackitem.NewStruct([]stackitem.Item{ + stackitem.Make(methods), + stackitem.Make(events), + }) +} + +// FromStackItem converts stackitem.Item to ABI. +func (a *ABI) FromStackItem(item stackitem.Item) error { + if item.Type() != stackitem.StructT { + return errors.New("invalid ABI stackitem type") + } + str := item.Value().([]stackitem.Item) + if len(str) != 2 { + return errors.New("invalid ABI stackitem length") + } + if str[0].Type() != stackitem.ArrayT { + return errors.New("invalid Methods stackitem type") + } + methods := str[0].Value().([]stackitem.Item) + a.Methods = make([]Method, len(methods)) + for i := range methods { + m := new(Method) + if err := m.FromStackItem(methods[i]); err != nil { + return err + } + a.Methods[i] = *m + } + if str[1].Type() != stackitem.ArrayT { + return errors.New("invalid Events stackitem type") + } + events := str[1].Value().([]stackitem.Item) + a.Events = make([]Event, len(events)) + for i := range events { + e := new(Event) + if err := e.FromStackItem(events[i]); err != nil { + return err + } + a.Events[i] = *e + } + return nil +} diff --git a/pkg/smartcontract/manifest/manifest.go b/pkg/smartcontract/manifest/manifest.go index e9db635a3..3a593ea21 100644 --- a/pkg/smartcontract/manifest/manifest.go +++ b/pkg/smartcontract/manifest/manifest.go @@ -13,33 +13,12 @@ const ( // MaxManifestSize is a max length for a valid contract manifest. MaxManifestSize = math.MaxUint16 - // MethodInit is a name for default initialization method. - MethodInit = "_initialize" - - // MethodDeploy is a name for default method called during contract deployment. - MethodDeploy = "_deploy" - - // MethodVerify is a name for default verification method. - MethodVerify = "verify" - - // MethodOnNEP17Payment is name of the method which is called when contract receives NEP-17 tokens. - MethodOnNEP17Payment = "onNEP17Payment" - - // MethodOnNEP11Payment is the name of the method which is called when contract receives NEP-11 tokens. - MethodOnNEP11Payment = "onNEP11Payment" - // NEP10StandardName represents the name of NEP10 smartcontract standard. NEP10StandardName = "NEP-10" // NEP17StandardName represents the name of NEP17 smartcontract standard. NEP17StandardName = "NEP-17" ) -// ABI represents a contract application binary interface. -type ABI struct { - Methods []Method `json:"methods"` - Events []Event `json:"events"` -} - // Manifest represens contract metadata. type Manifest struct { // Name is a contract's name. @@ -80,26 +59,6 @@ func DefaultManifest(name string) *Manifest { return m } -// GetMethod returns methods with the specified name. -func (a *ABI) GetMethod(name string, paramCount int) *Method { - for i := range a.Methods { - if a.Methods[i].Name == name && (paramCount == -1 || len(a.Methods[i].Parameters) == paramCount) { - return &a.Methods[i] - } - } - return nil -} - -// GetEvent returns event with the specified name. -func (a *ABI) GetEvent(name string) *Event { - for i := range a.Events { - if a.Events[i].Name == name { - return &a.Events[i] - } - } - return nil -} - // CanCall returns true is current contract is allowed to call // method of another contract with specified hash. func (m *Manifest) CanCall(hash util.Uint160, toCall *Manifest, method string) bool { @@ -246,55 +205,3 @@ func (m *Manifest) FromStackItem(item stackitem.Item) error { } return json.Unmarshal(extra, &m.Extra) } - -// ToStackItem converts ABI to stackitem.Item. -func (a *ABI) ToStackItem() stackitem.Item { - methods := make([]stackitem.Item, len(a.Methods)) - for i := range a.Methods { - methods[i] = a.Methods[i].ToStackItem() - } - events := make([]stackitem.Item, len(a.Events)) - for i := range a.Events { - events[i] = a.Events[i].ToStackItem() - } - return stackitem.NewStruct([]stackitem.Item{ - stackitem.Make(methods), - stackitem.Make(events), - }) -} - -// FromStackItem converts stackitem.Item to ABI. -func (a *ABI) FromStackItem(item stackitem.Item) error { - if item.Type() != stackitem.StructT { - return errors.New("invalid ABI stackitem type") - } - str := item.Value().([]stackitem.Item) - if len(str) != 2 { - return errors.New("invalid ABI stackitem length") - } - if str[0].Type() != stackitem.ArrayT { - return errors.New("invalid Methods stackitem type") - } - methods := str[0].Value().([]stackitem.Item) - a.Methods = make([]Method, len(methods)) - for i := range methods { - m := new(Method) - if err := m.FromStackItem(methods[i]); err != nil { - return err - } - a.Methods[i] = *m - } - if str[1].Type() != stackitem.ArrayT { - return errors.New("invalid Events stackitem type") - } - events := str[1].Value().([]stackitem.Item) - a.Events = make([]Event, len(events)) - for i := range events { - e := new(Event) - if err := e.FromStackItem(events[i]); err != nil { - return err - } - a.Events[i] = *e - } - return nil -}