Skip to content
16 changes: 13 additions & 3 deletions accounts/abi/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package abi

import "fmt"
import (
"fmt"
"unicode"
)

// ResolveNameConflict returns the next available name for a given thing.
// This helper can be used for lots of purposes:
Expand All @@ -29,11 +32,18 @@ import "fmt"
//
// Name conflicts are mostly resolved by adding number suffix. e.g. if the abi contains
// Methods "send" and "send1", ResolveNameConflict would return "send2" for input "send".
// If a method name starts with a number an M is prepended (e.g. 1method -> M1method).
// This will export the method in the ABI, which is okay since a leading number can be interpreted
// as an uppercase letter.
func ResolveNameConflict(rawName string, used func(string) bool) string {
name := rawName
prefixedName := rawName
if len(rawName) > 0 && unicode.IsDigit(rune(rawName[0])) {
prefixedName = fmt.Sprintf("%s%s", "M", rawName)
}
name := prefixedName
ok := used(name)
for idx := 0; ok; idx++ {
name = fmt.Sprintf("%s%d", rawName, idx)
name = fmt.Sprintf("%s%d", prefixedName, idx)
ok = used(name)
}
return name
Expand Down
65 changes: 65 additions & 0 deletions accounts/abi/utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package abi

import "testing"

func TestResolveNameConflict(t *testing.T) {
db := make(map[string]struct{})
used := func(s string) bool {
_, ok := db[s]
return ok
}

var tests = []struct {
input string
output string
}{
{
input: "1method",
output: "M1method",
},
{
input: "1method",
output: "M1method0",
},
{
input: "1method",
output: "M1method1",
},
{
input: "method",
output: "method",
},
{
input: "method",
output: "method0",
},
{
input: "",
output: "",
},
}

for _, test := range tests {
result := ResolveNameConflict(test.input, used)
if result != test.output {
t.Errorf("resolving name conflict failed, got %v want %v input %v", result, test.output, test.input)
}
db[result] = struct{}{}
}
}