Skip to content

Commit

Permalink
accounts/abi: change unpacking of abi fields w/ underscores (ethereum…
Browse files Browse the repository at this point in the history
  • Loading branch information
gzliudan committed Dec 21, 2024
1 parent 279a329 commit e45df2d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 49 deletions.
19 changes: 9 additions & 10 deletions accounts/abi/argument.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,21 +278,20 @@ func (arguments Arguments) Pack(args ...interface{}) ([]byte, error) {
return ret, nil
}

// capitalise makes the first character of a string upper case, also removing any
// prefixing underscores from the variable names.
func capitalise(input string) string {
for len(input) > 0 && input[0] == '_' {
input = input[1:]
}
if len(input) == 0 {
return ""
// ToCamelCase converts an under-score string to a camel-case string
func ToCamelCase(input string) string {
parts := strings.Split(input, "_")
for i, s := range parts {
if len(s) > 0 {
parts[i] = strings.ToUpper(s[:1]) + s[1:]
}
}
return strings.ToUpper(input[:1]) + input[1:]
return strings.Join(parts, "")
}

// unpackStruct extracts each argument into its corresponding struct field
func unpackStruct(value, reflectValue reflect.Value, arg Argument) error {
name := capitalise(arg.Name)
name := ToCamelCase(arg.Name)
typ := value.Type()
for j := 0; j < typ.NumField(); j++ {
// TODO read tags: `abi:"fieldName"`
Expand Down
42 changes: 4 additions & 38 deletions accounts/abi/bind/bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,48 +327,14 @@ var methodNormalizer = map[Lang]func(string) string{

// capitalise makes a camel-case string which starts with an upper case character.
func capitalise(input string) string {
for len(input) > 0 && input[0] == '_' {
input = input[1:]
}
if len(input) == 0 {
return ""
}
return toCamelCase(strings.ToUpper(input[:1]) + input[1:])
return abi.ToCamelCase(input)
}

// decapitalise makes a camel-case string which starts with a lower case character.
func decapitalise(input string) string {
for len(input) > 0 && input[0] == '_' {
input = input[1:]
}
if len(input) == 0 {
return ""
}
return toCamelCase(strings.ToLower(input[:1]) + input[1:])
}

// toCamelCase converts an under-score string to a camel-case string
func toCamelCase(input string) string {
toupper := false

result := ""
for k, v := range input {
switch {
case k == 0:
result = strings.ToUpper(string(input[0]))

case toupper:
result += strings.ToUpper(string(v))
toupper = false

case v == '_':
toupper = true

default:
result += string(v)
}
}
return result
// NOTE: This is the current behavior, it doesn't match the comment
// above and needs to be investigated.
return abi.ToCamelCase(input)
}

// structured checks whether a list of ABI data types has enough information to
Expand Down
2 changes: 1 addition & 1 deletion accounts/abi/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind,
func requireUniqueStructFieldNames(args Arguments) error {
exists := make(map[string]bool)
for _, arg := range args {
field := capitalise(arg.Name)
field := ToCamelCase(arg.Name)
if field == "" {
return errors.New("abi: purely underscored output cannot unpack to struct")
}
Expand Down
47 changes: 47 additions & 0 deletions accounts/abi/unpack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,53 @@ var unpackTests = []unpackTest{
Int2 *big.Int
}{big.NewInt(1), big.NewInt(2)},
},
{
def: `[{"name":"int_one","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
IntOne *big.Int
}{big.NewInt(1)},
},
{
def: `[{"name":"int__one","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
IntOne *big.Int
}{big.NewInt(1)},
},
{
def: `[{"name":"int_one_","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
IntOne *big.Int
}{big.NewInt(1)},
},
{
def: `[{"name":"int_one","type":"int256"}, {"name":"intone","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
IntOne *big.Int
Intone *big.Int
}{big.NewInt(1), big.NewInt(2)},
},
{
def: `[{"name":"___","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
IntOne *big.Int
Intone *big.Int
}{},
err: "abi: purely underscored output cannot unpack to struct",
},
{
def: `[{"name":"int_one","type":"int256"},{"name":"IntOne","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
want: struct {
Int1 *big.Int
Int2 *big.Int
}{},
err: "abi: multiple outputs mapping to the same struct field 'IntOne'",
},
{
def: `[{"name":"int","type":"int256"},{"name":"Int","type":"int256"}]`,
enc: "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
Expand Down

0 comments on commit e45df2d

Please sign in to comment.