accounts/abi: resolve name conflict for methods starting with a number (#26999)

This adds logic to prepend 'M' or 'E' to Solidity identifiers when they would
otherwise violate Go identifier naming rules.

Closes #26972

---------

Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Sina Mahmoodi <itz.s1na@gmail.com>
This commit is contained in:
Marius van der Wijden 2023-05-02 14:27:37 +02:00 committed by GitHub
parent 29c33d9bab
commit ac3418def6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 1 deletions

@ -133,12 +133,19 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
// Normalize the method for capital cases and non-anonymous inputs/outputs // Normalize the method for capital cases and non-anonymous inputs/outputs
normalized := original normalized := original
normalizedName := methodNormalizer[lang](alias(aliases, original.Name)) normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
// Ensure there is no duplicated identifier // Ensure there is no duplicated identifier
var identifiers = callIdentifiers var identifiers = callIdentifiers
if !original.IsConstant() { if !original.IsConstant() {
identifiers = transactIdentifiers identifiers = transactIdentifiers
} }
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("M%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := identifiers[name]
return ok
})
}
if identifiers[normalizedName] { if identifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName) return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
} }
@ -182,6 +189,14 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
// Ensure there is no duplicated identifier // Ensure there is no duplicated identifier
normalizedName := methodNormalizer[lang](alias(aliases, original.Name)) normalizedName := methodNormalizer[lang](alias(aliases, original.Name))
// Name shouldn't start with a digit. It will make the generated code invalid.
if len(normalizedName) > 0 && unicode.IsDigit(rune(normalizedName[0])) {
normalizedName = fmt.Sprintf("E%s", normalizedName)
normalizedName = abi.ResolveNameConflict(normalizedName, func(name string) bool {
_, ok := eventIdentifiers[name]
return ok
})
}
if eventIdentifiers[normalizedName] { if eventIdentifiers[normalizedName] {
return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName) return "", fmt.Errorf("duplicated identifier \"%s\"(normalized \"%s\"), use --alias for renaming", original.Name, normalizedName)
} }

@ -2038,6 +2038,29 @@ var bindTests = []struct {
t.Errorf("error deploying the contract: %v", err) t.Errorf("error deploying the contract: %v", err)
} }
`, `,
}, {
name: "NumericMethodName",
contract: `
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.22 <0.9.0;
contract NumericMethodName {
event _1TestEvent(address _param);
function _1test() public pure {}
function __1test() public pure {}
function __2test() public pure {}
}
`,
bytecode: []string{"0x6080604052348015600f57600080fd5b5060958061001e6000396000f3fe6080604052348015600f57600080fd5b5060043610603c5760003560e01c80639d993132146041578063d02767c7146049578063ffa02795146051575b600080fd5b60476059565b005b604f605b565b005b6057605d565b005b565b565b56fea26469706673582212200382ca602dff96a7e2ba54657985e2b4ac423a56abe4a1f0667bc635c4d4371f64736f6c63430008110033"},
abi: []string{`[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_param","type":"address"}],"name":"_1TestEvent","type":"event"},{"inputs":[],"name":"_1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__1test","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"__2test","outputs":[],"stateMutability":"pure","type":"function"}]`},
imports: `
"github.com/ethereum/go-ethereum/common"
`,
tester: `
if b, err := NewNumericMethodName(common.Address{}, nil); b == nil || err != nil {
t.Fatalf("combined binding (%v) nil or error (%v) not nil", b, nil)
}
`,
}, },
} }