selector_parser.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright 2022 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package abi
  17. import (
  18. "fmt"
  19. )
  20. type SelectorMarshaling struct {
  21. Name string `json:"name"`
  22. Type string `json:"type"`
  23. Inputs []ArgumentMarshaling `json:"inputs"`
  24. }
  25. func isDigit(c byte) bool {
  26. return c >= '0' && c <= '9'
  27. }
  28. func isAlpha(c byte) bool {
  29. return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
  30. }
  31. func isIdentifierSymbol(c byte) bool {
  32. return c == '$' || c == '_'
  33. }
  34. func parseToken(unescapedSelector string, isIdent bool) (string, string, error) {
  35. if len(unescapedSelector) == 0 {
  36. return "", "", fmt.Errorf("empty token")
  37. }
  38. firstChar := unescapedSelector[0]
  39. position := 1
  40. if !(isAlpha(firstChar) || (isIdent && isIdentifierSymbol(firstChar))) {
  41. return "", "", fmt.Errorf("invalid token start: %c", firstChar)
  42. }
  43. for position < len(unescapedSelector) {
  44. char := unescapedSelector[position]
  45. if !(isAlpha(char) || isDigit(char) || (isIdent && isIdentifierSymbol(char))) {
  46. break
  47. }
  48. position++
  49. }
  50. return unescapedSelector[:position], unescapedSelector[position:], nil
  51. }
  52. func parseIdentifier(unescapedSelector string) (string, string, error) {
  53. return parseToken(unescapedSelector, true)
  54. }
  55. func parseElementaryType(unescapedSelector string) (string, string, error) {
  56. parsedType, rest, err := parseToken(unescapedSelector, false)
  57. if err != nil {
  58. return "", "", fmt.Errorf("failed to parse elementary type: %v", err)
  59. }
  60. // handle arrays
  61. for len(rest) > 0 && rest[0] == '[' {
  62. parsedType = parsedType + string(rest[0])
  63. rest = rest[1:]
  64. for len(rest) > 0 && isDigit(rest[0]) {
  65. parsedType = parsedType + string(rest[0])
  66. rest = rest[1:]
  67. }
  68. if len(rest) == 0 || rest[0] != ']' {
  69. return "", "", fmt.Errorf("failed to parse array: expected ']', got %c", unescapedSelector[0])
  70. }
  71. parsedType = parsedType + string(rest[0])
  72. rest = rest[1:]
  73. }
  74. return parsedType, rest, nil
  75. }
  76. func parseCompositeType(unescapedSelector string) ([]interface{}, string, error) {
  77. if len(unescapedSelector) == 0 || unescapedSelector[0] != '(' {
  78. return nil, "", fmt.Errorf("expected '(', got %c", unescapedSelector[0])
  79. }
  80. parsedType, rest, err := parseType(unescapedSelector[1:])
  81. if err != nil {
  82. return nil, "", fmt.Errorf("failed to parse type: %v", err)
  83. }
  84. result := []interface{}{parsedType}
  85. for len(rest) > 0 && rest[0] != ')' {
  86. parsedType, rest, err = parseType(rest[1:])
  87. if err != nil {
  88. return nil, "", fmt.Errorf("failed to parse type: %v", err)
  89. }
  90. result = append(result, parsedType)
  91. }
  92. if len(rest) == 0 || rest[0] != ')' {
  93. return nil, "", fmt.Errorf("expected ')', got '%s'", rest)
  94. }
  95. if len(rest) >= 3 && rest[1] == '[' && rest[2] == ']' {
  96. return append(result, "[]"), rest[3:], nil
  97. }
  98. return result, rest[1:], nil
  99. }
  100. func parseType(unescapedSelector string) (interface{}, string, error) {
  101. if len(unescapedSelector) == 0 {
  102. return nil, "", fmt.Errorf("empty type")
  103. }
  104. if unescapedSelector[0] == '(' {
  105. return parseCompositeType(unescapedSelector)
  106. } else {
  107. return parseElementaryType(unescapedSelector)
  108. }
  109. }
  110. func assembleArgs(args []interface{}) ([]ArgumentMarshaling, error) {
  111. arguments := make([]ArgumentMarshaling, 0)
  112. for i, arg := range args {
  113. // generate dummy name to avoid unmarshal issues
  114. name := fmt.Sprintf("name%d", i)
  115. if s, ok := arg.(string); ok {
  116. arguments = append(arguments, ArgumentMarshaling{name, s, s, nil, false})
  117. } else if components, ok := arg.([]interface{}); ok {
  118. subArgs, err := assembleArgs(components)
  119. if err != nil {
  120. return nil, fmt.Errorf("failed to assemble components: %v", err)
  121. }
  122. tupleType := "tuple"
  123. if len(subArgs) != 0 && subArgs[len(subArgs)-1].Type == "[]" {
  124. subArgs = subArgs[:len(subArgs)-1]
  125. tupleType = "tuple[]"
  126. }
  127. arguments = append(arguments, ArgumentMarshaling{name, tupleType, tupleType, subArgs, false})
  128. } else {
  129. return nil, fmt.Errorf("failed to assemble args: unexpected type %T", arg)
  130. }
  131. }
  132. return arguments, nil
  133. }
  134. // ParseSelector converts a method selector into a struct that can be JSON encoded
  135. // and consumed by other functions in this package.
  136. // Note, although uppercase letters are not part of the ABI spec, this function
  137. // still accepts it as the general format is valid.
  138. func ParseSelector(unescapedSelector string) (SelectorMarshaling, error) {
  139. name, rest, err := parseIdentifier(unescapedSelector)
  140. if err != nil {
  141. return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err)
  142. }
  143. args := []interface{}{}
  144. if len(rest) >= 2 && rest[0] == '(' && rest[1] == ')' {
  145. rest = rest[2:]
  146. } else {
  147. args, rest, err = parseCompositeType(rest)
  148. if err != nil {
  149. return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': %v", unescapedSelector, err)
  150. }
  151. }
  152. if len(rest) > 0 {
  153. return SelectorMarshaling{}, fmt.Errorf("failed to parse selector '%s': unexpected string '%s'", unescapedSelector, rest)
  154. }
  155. // Reassemble the fake ABI and construct the JSON
  156. fakeArgs, err := assembleArgs(args)
  157. if err != nil {
  158. return SelectorMarshaling{}, fmt.Errorf("failed to parse selector: %v", err)
  159. }
  160. return SelectorMarshaling{name, "function", fakeArgs}, nil
  161. }