mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
accounts/abi: fix various issues
The fixed issues include: (1) If there is no return in a call function, unpack should return nil error (2) For some functions which have struct array as parameter, it will also be detected and generate the struct definition (3) For event, if it has non-indexed parameter, the parameter name will also be assigned if empty. Also the internal struct will be detected and generate struct defition if not exist. (4) Fix annotation generation in event function
This commit is contained in:
parent
e306304414
commit
761c731ab2
4 changed files with 37 additions and 18 deletions
|
|
@ -75,9 +75,6 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
|
||||||
|
|
||||||
// Unpack output in v according to the abi specification
|
// Unpack output in v according to the abi specification
|
||||||
func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
|
func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
|
||||||
if len(data) == 0 {
|
|
||||||
return fmt.Errorf("abi: unmarshalling empty output")
|
|
||||||
}
|
|
||||||
// since there can't be naming collisions with contracts and events,
|
// since there can't be naming collisions with contracts and events,
|
||||||
// we need to decide whether we're calling a method or an event
|
// we need to decide whether we're calling a method or an event
|
||||||
if method, ok := abi.Methods[name]; ok {
|
if method, ok := abi.Methods[name]; ok {
|
||||||
|
|
@ -94,9 +91,6 @@ func (abi ABI) Unpack(v interface{}, name string, data []byte) (err error) {
|
||||||
|
|
||||||
// UnpackIntoMap unpacks a log into the provided map[string]interface{}
|
// UnpackIntoMap unpacks a log into the provided map[string]interface{}
|
||||||
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
|
func (abi ABI) UnpackIntoMap(v map[string]interface{}, name string, data []byte) (err error) {
|
||||||
if len(data) == 0 {
|
|
||||||
return fmt.Errorf("abi: unmarshalling empty output")
|
|
||||||
}
|
|
||||||
// since there can't be naming collisions with contracts and events,
|
// since there can't be naming collisions with contracts and events,
|
||||||
// we need to decide whether we're calling a method or an event
|
// we need to decide whether we're calling a method or an event
|
||||||
if method, ok := abi.Methods[name]; ok {
|
if method, ok := abi.Methods[name]; ok {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,13 @@ func (arguments Arguments) isTuple() bool {
|
||||||
|
|
||||||
// Unpack performs the operation hexdata -> Go format
|
// Unpack performs the operation hexdata -> Go format
|
||||||
func (arguments Arguments) Unpack(v interface{}, data []byte) error {
|
func (arguments Arguments) Unpack(v interface{}, data []byte) error {
|
||||||
|
if len(data) == 0 {
|
||||||
|
if len(arguments) != 0 {
|
||||||
|
return fmt.Errorf("abi: unmarshalling empty output")
|
||||||
|
} else {
|
||||||
|
return nil // Nothing to unmarshal, return
|
||||||
|
}
|
||||||
|
}
|
||||||
// make sure the passed value is arguments pointer
|
// make sure the passed value is arguments pointer
|
||||||
if reflect.Ptr != reflect.ValueOf(v).Kind() {
|
if reflect.Ptr != reflect.ValueOf(v).Kind() {
|
||||||
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
|
return fmt.Errorf("abi: Unpack(non-pointer %T)", v)
|
||||||
|
|
@ -104,11 +111,17 @@ func (arguments Arguments) Unpack(v interface{}, data []byte) error {
|
||||||
|
|
||||||
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value
|
// UnpackIntoMap performs the operation hexdata -> mapping of argument name to argument value
|
||||||
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
|
func (arguments Arguments) UnpackIntoMap(v map[string]interface{}, data []byte) error {
|
||||||
|
if len(data) == 0 {
|
||||||
|
if len(arguments) != 0 {
|
||||||
|
return fmt.Errorf("abi: unmarshalling empty output")
|
||||||
|
} else {
|
||||||
|
return nil // Nothing to unmarshal, return
|
||||||
|
}
|
||||||
|
}
|
||||||
marshalledValues, err := arguments.UnpackValues(data)
|
marshalledValues, err := arguments.UnpackValues(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return arguments.unpackIntoMap(v, marshalledValues)
|
return arguments.unpackIntoMap(v, marshalledValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
if input.Name == "" {
|
if input.Name == "" {
|
||||||
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
||||||
}
|
}
|
||||||
if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist {
|
if hasStruct(input.Type) {
|
||||||
bindStructType[lang](input.Type, structs)
|
bindStructType[lang](input.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +96,7 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
if output.Name != "" {
|
if output.Name != "" {
|
||||||
normalized.Outputs[j].Name = capitalise(output.Name)
|
normalized.Outputs[j].Name = capitalise(output.Name)
|
||||||
}
|
}
|
||||||
if _, exist := structs[output.Type.String()]; output.Type.T == abi.TupleTy && !exist {
|
if hasStruct(output.Type) {
|
||||||
bindStructType[lang](output.Type, structs)
|
bindStructType[lang](output.Type, structs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,14 +119,11 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||||
normalized.Inputs = make([]abi.Argument, len(original.Inputs))
|
normalized.Inputs = make([]abi.Argument, len(original.Inputs))
|
||||||
copy(normalized.Inputs, original.Inputs)
|
copy(normalized.Inputs, original.Inputs)
|
||||||
for j, input := range normalized.Inputs {
|
for j, input := range normalized.Inputs {
|
||||||
// Indexed fields are input, non-indexed ones are outputs
|
if input.Name == "" {
|
||||||
if input.Indexed {
|
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
||||||
if input.Name == "" {
|
}
|
||||||
normalized.Inputs[j].Name = fmt.Sprintf("arg%d", j)
|
if hasStruct(input.Type) {
|
||||||
}
|
bindStructType[lang](input.Type, structs)
|
||||||
if _, exist := structs[input.Type.String()]; input.Type.T == abi.TupleTy && !exist {
|
|
||||||
bindStructType[lang](input.Type, structs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Append the event to the accumulator list
|
// Append the event to the accumulator list
|
||||||
|
|
@ -497,6 +494,21 @@ func structured(args abi.Arguments) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasStruct returns an indicator whether the given type is struct, struct slice
|
||||||
|
// or struct array.
|
||||||
|
func hasStruct(t abi.Type) bool {
|
||||||
|
switch t.T {
|
||||||
|
case abi.SliceTy:
|
||||||
|
return hasStruct(*t.Elem)
|
||||||
|
case abi.ArrayTy:
|
||||||
|
return hasStruct(*t.Elem)
|
||||||
|
case abi.TupleTy:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// resolveArgName converts a raw argument representation into a user friendly format.
|
// resolveArgName converts a raw argument representation into a user friendly format.
|
||||||
func resolveArgName(arg abi.Argument, structs map[string]*tmplStruct) string {
|
func resolveArgName(arg abi.Argument, structs map[string]*tmplStruct) string {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -483,7 +483,7 @@ var (
|
||||||
|
|
||||||
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
// Parse{{.Normalized.Name}} is a log parse operation binding the contract event 0x{{printf "%x" .Original.ID}}.
|
||||||
//
|
//
|
||||||
// Solidity: {{.Original.String}}
|
// Solidity: {{formatevent .Original $structs}}
|
||||||
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
func (_{{$contract.Type}} *{{$contract.Type}}Filterer) Parse{{.Normalized.Name}}(log types.Log) (*{{$contract.Type}}{{.Normalized.Name}}, error) {
|
||||||
event := new({{$contract.Type}}{{.Normalized.Name}})
|
event := new({{$contract.Type}}{{.Normalized.Name}})
|
||||||
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
if err := _{{$contract.Type}}.contract.UnpackLog(event, "{{.Original.Name}}", log); err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue