Skip to content

Commit

Permalink
Multi Contract ABI resolver fix (phase A) (#27)
Browse files Browse the repository at this point in the history
* Fixing variable internal type if type is custom interface/contract
* Fixing changes in types. No longer common directory. Resolving issues within abi and improving unit test
  • Loading branch information
0x19 authored Jul 11, 2023
1 parent bb910d4 commit 6fca24f
Show file tree
Hide file tree
Showing 10 changed files with 1,518 additions and 69 deletions.
30 changes: 26 additions & 4 deletions abis/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package abis
import (
"regexp"
"strings"

"github.com/txpull/solgo/common"
)

// normalizeTypeName normalizes the type name in Solidity to its canonical form.
Expand All @@ -25,7 +23,7 @@ func normalizeTypeName(typeName string) string {

// normalizeStructTypeName normalizes the type name of a struct in Solidity to its canonical form.
// For example, "structName[]" is normalized to "tuple[]", and "structName" is normalized to "tuple".
func normalizeStructTypeName(definedStructs map[string]common.MethodIO, typeName string) string {
func normalizeStructTypeName(definedStructs map[string]MethodIO, typeName string) string {
switch {
case strings.HasSuffix(typeName, "[]") && isStructType(definedStructs, strings.TrimSuffix(typeName, "[]")):
// Handle array of structs
Expand All @@ -44,7 +42,7 @@ func isMappingType(name string) bool {
// isStructType checks if a type name corresponds to a defined struct.
// definedStructs is a map from struct names to MethodIO objects representing the struct located in the AbiParser.
// Returns true if the type name corresponds to a defined struct, false otherwise.
func isStructType(definedStructs map[string]common.MethodIO, typeName string) bool {
func isStructType(definedStructs map[string]MethodIO, typeName string) bool {
typeName = strings.TrimRight(typeName, "[]")
_, exists := definedStructs[typeName]
return exists
Expand All @@ -59,6 +57,30 @@ func isEnumType(definedEnums map[string]bool, typeName string) bool {
return exists
}

// isContractType checks if a given type is a contract type.
// It takes a map of defined contracts and a type name as arguments.
// The function returns true if the type name exists in the map of defined contracts, indicating that it is a contract type.
func isContractType(definedContracts map[string]ContractDefinition, typeName string) bool {
_, exists := definedContracts[typeName]
return exists
}

// isInterfaceType checks if a given type is an interface type.
// It takes a map of defined interfaces and a type name as arguments.
// The function returns true if the type name exists in the map of defined interfaces, indicating that it is an interface type.
func isInterfaceType(definedInterfaces map[string]bool, typeName string) bool {
_, exists := definedInterfaces[typeName]
return exists
}

// isLibraryType checks if a given type is a library type.
// It takes a map of defined libraries and a type name as arguments.
// The function returns true if the type name exists in the map of defined libraries, indicating that it is a library type.
func isLibraryType(definedLibraries map[string]bool, typeName string) bool {
_, exists := definedLibraries[typeName]
return exists
}

// parseMappingType parses a mapping type in Solidity ABI.
// It takes a string of the form "mapping(keyType => valueType)" and returns three values:
// - A boolean indicating whether the parsing was successful. If the string is not a mapping type, this will be false.
Expand Down
31 changes: 26 additions & 5 deletions abis/listener.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package abis

import (
"github.com/txpull/solgo/common"
"github.com/txpull/solgo/parser"
"go.uber.org/zap"
)
Expand All @@ -18,10 +17,12 @@ type AbiListener struct {
// It returns a pointer to the newly created AbiListener.
func NewAbiListener() *AbiListener {
return &AbiListener{parser: &AbiParser{
abi: common.ABI{},
definedStructs: make(map[string]common.MethodIO),
definedEnums: make(map[string]bool), // map to keep track of defined enum types

abi: ABI{},
definedStructs: make(map[string]MethodIO),
definedEnums: make(map[string]bool), // map to keep track of defined enum types
definedInterfaces: make(map[string]bool),
definedLibraries: make(map[string]bool),
definedContracts: make(map[string]ContractDefinition),
}}
}

Expand All @@ -30,6 +31,26 @@ func NewAbiListener() *AbiListener {
// Later on we use contract name to define internalType of the tuple/struct type.
func (l *AbiListener) EnterContractDefinition(ctx *parser.ContractDefinitionContext) {
l.parser.contractName = ctx.Identifier().GetText() // get the contract name

if _, ok := l.parser.definedContracts[l.parser.contractName]; !ok {
l.parser.definedContracts[l.parser.contractName] = ContractDefinition{
IsAbstract: func() bool {
return ctx.Abstract() != nil
}(),
}
}
}

func (l *AbiListener) EnterInterfaceDefinition(ctx *parser.InterfaceDefinitionContext) {
if _, ok := l.parser.definedInterfaces[ctx.Identifier().GetText()]; !ok {
l.parser.definedInterfaces[ctx.Identifier().GetText()] = true
}
}

func (l *AbiListener) EnterLibraryDefinition(ctx *parser.LibraryDefinitionContext) {
if _, ok := l.parser.definedLibraries[ctx.Identifier().GetText()]; !ok {
l.parser.definedLibraries[ctx.Identifier().GetText()] = true
}
}

// EnterStateVariableDeclaration is called when the parser enters a state variable declaration.
Expand Down
5 changes: 5 additions & 0 deletions abis/listener_test.go

Large diffs are not rendered by default.

Loading

0 comments on commit 6fca24f

Please sign in to comment.