From 9067b4c503847de2bd9beec2f58efd81bb40b18b Mon Sep 17 00:00:00 2001 From: Nevio Date: Mon, 29 Jul 2024 16:09:36 +0200 Subject: [PATCH] Local with upstream --- abi/contract.go | 9 ++++++++- abi/state_variable.go | 5 ----- ast/modifier.go | 5 ++--- ast/parameter.go | 18 ++++++++++++++---- ast/primary_expression.go | 7 +++++++ ast/reference.go | 10 ++++++---- ast/storage.go | 35 +++++++++++++++++++++++++---------- ast/tree.go | 4 ++-- ast/type_name.go | 22 +--------------------- contracts/constructor.go | 4 +++- ir/function_call.go | 4 ++++ ir/standards.go | 20 ++++++++------------ ir/variables.go | 7 +++---- parser/solidity_parser.go | 5 ++++- storage/reader.go | 6 +++--- 15 files changed, 90 insertions(+), 71 deletions(-) diff --git a/abi/contract.go b/abi/contract.go index ddb95307..3a9bd784 100644 --- a/abi/contract.go +++ b/abi/contract.go @@ -51,6 +51,11 @@ func (b *Builder) processContract(contract *ir.Contract) (*Contract, error) { // Process state variables. for _, stateVar := range contract.GetStateVariables() { + // Some old contracts will have this broken. It's related to 0.4 contracts. + // Better to have at least something then nothing at all in this point. + if stateVar.Name == "" && stateVar.GetTypeDescription() == nil { + continue + } method := b.processStateVariable(stateVar) toReturn = append(toReturn, method) } @@ -143,7 +148,9 @@ func (b *Builder) buildMethodIO(method MethodIO, typeDescr *ast.TypeDescription) } method.InternalType = typeDescr.GetString() case "struct": - return b.resolver.ResolveStructType(typeDescr) + structMember := b.resolver.ResolveStructType(typeDescr) + structMember.Name = method.Name + return structMember default: method.Type = typeName method.InternalType = typeDescr.GetString() diff --git a/abi/state_variable.go b/abi/state_variable.go index b804290d..c7818639 100644 --- a/abi/state_variable.go +++ b/abi/state_variable.go @@ -2,7 +2,6 @@ package abi import ( "github.com/unpackdev/solgo/ir" - "github.com/unpackdev/solgo/utils" ) // processStateVariable processes the provided StateVariable from the IR and constructs a Method representation. @@ -17,10 +16,6 @@ func (b *Builder) processStateVariable(stateVar *ir.StateVariable) *Method { StateMutability: b.normalizeStateMutability(stateVar.GetStateMutability()), } - if stateVar.GetTypeDescription() == nil { - utils.DumpNodeWithExit(stateVar) - } - typeName := b.resolver.ResolveType(stateVar.GetTypeDescription()) switch typeName { diff --git a/ast/modifier.go b/ast/modifier.go index 2fa1845f..fad4803f 100644 --- a/ast/modifier.go +++ b/ast/modifier.go @@ -215,11 +215,9 @@ func (m *ModifierDefinition) ParseDefinition( parameters.Src = m.Src } m.Parameters = parameters - + bodyNode := NewBodyNode(m.ASTBuilder, false) if ctx.Block() != nil && !ctx.Block().IsEmpty() { - bodyNode := NewBodyNode(m.ASTBuilder, false) bodyNode.ParseBlock(unit, contractNode, m, ctx.Block()) - m.Body = bodyNode if ctx.Block().AllUncheckedBlock() != nil { for _, uncheckedCtx := range ctx.Block().AllUncheckedBlock() { @@ -229,6 +227,7 @@ func (m *ModifierDefinition) ParseDefinition( } } } + m.Body = bodyNode m.currentModifiers = append(m.currentModifiers, m) return m diff --git a/ast/parameter.go b/ast/parameter.go index 7c2f7287..f30a2b7a 100644 --- a/ast/parameter.go +++ b/ast/parameter.go @@ -285,11 +285,21 @@ func (p *Parameter) Parse(unit *SourceUnit[Node[ast_pb.SourceUnit]], fnNode Node p.TypeDescription = typeName.GetTypeDescription() p.currentVariables = append(p.currentVariables, p) - if refId, refTypeDescription := p.GetResolver().ResolveByNode(typeName, typeName.Name); refTypeDescription != nil { - typeName.ReferencedDeclaration = refId - typeName.TypeDescription = refTypeDescription - p.TypeDescription = typeName.GetTypeDescription() + if p.TypeDescription == nil { + if refId, refTypeDescription := p.GetResolver().ResolveByNode(typeName, typeName.Name); refTypeDescription != nil { + typeName.ReferencedDeclaration = refId + typeName.TypeDescription = refTypeDescription + p.TypeDescription = typeName.GetTypeDescription() + } + } + + if p.Name == "" && p.TypeName != nil && p.TypeName.Name != "" { + p.Name = p.TypeName.Name } + + /* if p.Id == 4253 { + utils.DumpNodeWithExit(p) + }*/ } // ParseEventParameter parses the event parameter context and populates the Parameter fields for event parameters. diff --git a/ast/primary_expression.go b/ast/primary_expression.go index ba3e327f..fecf760e 100644 --- a/ast/primary_expression.go +++ b/ast/primary_expression.go @@ -217,6 +217,13 @@ func (p *PrimaryExpression) Parse( } } + if ctx.GetText() == "throw" { + p.TypeDescription = &TypeDescription{ + TypeIdentifier: "t_magic_throw", + TypeString: "throw", + } + } + if ctx.GetText() == "block" { p.TypeDescription = &TypeDescription{ TypeIdentifier: "t_magic_block", diff --git a/ast/reference.go b/ast/reference.go index 347186f6..e5cada3e 100644 --- a/ast/reference.go +++ b/ast/reference.go @@ -56,10 +56,8 @@ func (r *Resolver) ResolveByNode(node Node[NodeType], name string) (int64, *Type isPrefixSlice := strings.HasPrefix(name, "[]") cleanedName := name - if isSlice { - cleanedName = strings.TrimSuffix(name, "[]") - } else if isPrefixSlice { - cleanedName = strings.TrimPrefix(name, "[]") + if isSlice || isPrefixSlice { + cleanedName = strings.ReplaceAll(name, "[]", "") } rNode, rNodeType := r.resolveByNode(cleanedName, node) @@ -479,6 +477,10 @@ func (r *Resolver) byEvents(name string) (int64, *TypeDescription) { } func (r *Resolver) byGlobals(name string) (int64, *TypeDescription) { + if strings.Contains(name, "[]") { + name = strings.ReplaceAll(name, "[]", "") + } + for _, node := range r.globalDefinitions { switch nodeCtx := node.(type) { case *EnumDefinition: diff --git a/ast/storage.go b/ast/storage.go index 63b84907..aa265365 100644 --- a/ast/storage.go +++ b/ast/storage.go @@ -56,7 +56,7 @@ func (t *TypeName) StorageSize() (int64, bool) { if strings.Contains(t.GetTypeDescription().GetString(), "int_const") { rationalParts := strings.Split(t.GetTypeDescription().GetIdentifier(), "_by_") if len(rationalParts) == 2 { - numerator, err1 := strconv.Atoi(rationalParts[0][len(rationalParts[0])-2:]) + numerator, err1 := strconv.Atoi(strings.Replace(rationalParts[0], "t_rational_", "", -1)) denominator, err2 := strconv.Atoi(rationalParts[1]) if err1 == nil && err2 == nil { bitSize := int64(math.Ceil(math.Log2(float64(numerator / denominator)))) @@ -91,8 +91,17 @@ func elementaryTypeSizeInBits(typeName string) (int64, bool) { // `bytes` with a fixed size, and dynamically sized types like `string` and `bytes`. // Returns the size and a boolean indicating if the type is recognized. func getTypeSizeInBits(typeName string) (int64, bool) { - // TODO: Make this actually work better... Figure out dynamically what is the size of an array - typeName = strings.TrimSuffix(typeName, "[]") + // Handle array types + if strings.HasSuffix(typeName, "[]") { + elementType := strings.TrimSuffix(typeName, "[]") + elementSize, ok := getTypeSizeInBits(elementType) + if !ok { + return 0, false + } + // For dynamic arrays, the size in bits depends on the actual content + // and includes the overhead for array length (256 bits). + return elementSize + 256, true + } switch { case typeName == "bool": @@ -113,21 +122,27 @@ func getTypeSizeInBits(typeName string) (int64, bool) { } return int64(bitSize), true - + case typeName == "string": + // Dynamic-size types; the size depends on the actual content. + // It's hard to determine the exact size in bits without the content. + // Returning a default size for the pointer. + return 256, true + case typeName == "bytes": + // Dynamic-size types; the size depends on the actual content. + // It's hard to determine the exact size in bits without the content. + // Returning a default size for the pointer. + return 256, true case strings.HasPrefix(typeName, "bytes"): byteSizeStr := strings.TrimPrefix(typeName, "bytes") + if byteSizeStr == "" { + return 0, false // Dynamic-sized bytes array, which is not supported + } byteSize, err := strconv.Atoi(byteSizeStr) if err != nil || byteSize < 1 || byteSize > 32 { return 0, false } return int64(byteSize) * 8, true - case typeName == "string", typeName == "bytes": - // Dynamic-size types; the size depends on the actual content. - // It's hard to determine the exact size in bits without the content. - // Returning a default size for the pointer. - return 256, true - default: return 0, false // Type not recognized } diff --git a/ast/tree.go b/ast/tree.go index 4a1b6ac5..07c0a541 100644 --- a/ast/tree.go +++ b/ast/tree.go @@ -70,13 +70,13 @@ func (t *Tree) UpdateNodeReferenceById(nodeId int64, nodeRefId int64, typeRef *T return false } - for _, child := range t.astRoot.GetNodes() { + for _, child := range t.astRoot.GetGlobalNodes() { if n := t.byRecursiveReferenceUpdate(child, nodeId, nodeRefId, typeRef); n { return n } } - for _, child := range t.astRoot.GetGlobalNodes() { + for _, child := range t.astRoot.GetNodes() { if n := t.byRecursiveReferenceUpdate(child, nodeId, nodeRefId, typeRef); n { return n } diff --git a/ast/type_name.go b/ast/type_name.go index 1c5193f6..eaff87b3 100644 --- a/ast/type_name.go +++ b/ast/type_name.go @@ -75,30 +75,10 @@ func (t *TypeName) SetReferenceDescriptor(refId int64, refDesc *TypeDescription) if strings.HasSuffix(t.Name, "[]") && refDesc != nil { if !strings.HasSuffix(refDesc.TypeString, "[]") { t.TypeDescription.TypeString += "[]" - /*if t.PathNode != nil && t.PathNode.TypeDescription != nil { - if !strings.HasSuffix(t.PathNode.Name, "[]") { - if strings.HasSuffix(t.PathNode.TypeDescription.TypeString, "[]") { - // Kumbayaa through fucking recursion... - t.PathNode.TypeDescription.TypeString = strings.TrimSuffix( - t.PathNode.TypeDescription.TypeString, "[]", - ) - } - } - }*/ + return true } } - // Lets update the parent node as well in case that type description is not set... - /* parentNodeId := t.GetSrc().GetParentIndex() - - if parentNodeId > 0 { - if parentNode := t.GetTree().GetById(parentNodeId); parentNode != nil { - if parentNode.GetTypeDescription() == nil { - parentNode.SetReferenceDescriptor(refId, refDesc) - } - } - } - */ return true } diff --git a/contracts/constructor.go b/contracts/constructor.go index 99991d66..dc4a74e5 100644 --- a/contracts/constructor.go +++ b/contracts/constructor.go @@ -29,6 +29,7 @@ func (c *Contract) DiscoverConstructor(ctx context.Context) error { abiRoot != nil && abiRoot.GetEntryContract().GetMethodByType("constructor") != nil { cAbi, _ := utils.ToJSON(abiRoot.GetEntryContract().GetMethodByType("constructor")) constructorAbi := fmt.Sprintf("[%s]", string(cAbi)) + //utils.DumpNodeWithExit(abiRoot.GetEntryContract().GetMethodByType("constructor")) //utils.DumpNodeWithExit(irRoot.GetEntryContract().GetConstructor().GetParameters()) tx := c.descriptor.Transaction deployedBytecode := c.descriptor.DeployedBytecode @@ -50,7 +51,8 @@ func (c *Contract) DiscoverConstructor(ctx context.Context) error { // TODO: Fix // - 0x47CE0C6eD5B0Ce3d3A51fdb1C52DC66a7c3c2936 (239 bytes more) - Some shitty text... - + //spew.Dump(hex.EncodeToString(tx.Data())) + //fmt.Println("") //spew.Dump(hex.EncodeToString(adjustedData[constructorDataIndex:])) //spew.Dump(constructorAbi) // 239 //utils.DumpNodeWithExit(irRoot.GetEntryContract().GetConstructor().GetParameters()) diff --git a/ir/function_call.go b/ir/function_call.go index c185ce28..d23eedcf 100644 --- a/ir/function_call.go +++ b/ir/function_call.go @@ -1,6 +1,7 @@ package ir import ( + "github.com/unpackdev/solgo/utils" "strings" v3 "github.com/cncf/xds/go/xds/type/v3" @@ -139,6 +140,9 @@ func (b *Builder) processFunctionCall(fn *Function, unit *ast.FunctionCall) *Fun } for _, arg := range unit.GetArguments() { + if arg.GetTypeDescription() == nil { + utils.DumpNodeWithExit(arg) + } toReturn.ArgumentTypes = append(toReturn.ArgumentTypes, arg.GetTypeDescription().ToProto()) } diff --git a/ir/standards.go b/ir/standards.go index 9e72d08a..bcff441e 100644 --- a/ir/standards.go +++ b/ir/standards.go @@ -3,7 +3,6 @@ package ir import ( ir_pb "github.com/unpackdev/protos/dist/go/ir" "github.com/unpackdev/solgo/standards" - "github.com/unpackdev/solgo/utils" ) // Standard represents a specific Ethereum Improvement Proposal standard that a contract may adhere to. @@ -70,6 +69,9 @@ func (b *Builder) processEips(root *RootSourceUnit) { outputs := make([]standards.Output, 0) for _, param := range function.GetParameters() { + if param.GetTypeDescription() == nil { + //utils.DumpNodeWithExit(param) + } inputs = append(inputs, standards.Input{ Type: param.GetTypeDescription().GetString(), Indexed: false, // Specific to events... @@ -77,18 +79,12 @@ func (b *Builder) processEips(root *RootSourceUnit) { } for _, ret := range function.GetReturnStatements() { - if ret.GetTypeDescription() != nil { - outputs = append(outputs, standards.Output{ - Type: "t_unknown", // Will fix this later on with upgrade of parser to support solidity 0.5+ - }) - } else { - if ret.GetTypeDescription() == nil { - utils.DumpNodeWithExit(function) - } - outputs = append(outputs, standards.Output{ - Type: ret.GetTypeDescription().GetString(), - }) + if ret.GetTypeDescription() == nil { + //utils.DumpNodeWithExit(function) } + outputs = append(outputs, standards.Output{ + Type: ret.GetTypeDescription().GetString(), + }) } contract.Functions = append(contract.Functions, standards.StandardFunction{ diff --git a/ir/variables.go b/ir/variables.go index c5cd5b2b..6ceac67f 100644 --- a/ir/variables.go +++ b/ir/variables.go @@ -1,7 +1,6 @@ package ir import ( - "github.com/unpackdev/solgo/utils" "strings" ast_pb "github.com/unpackdev/protos/dist/go/ast" @@ -128,9 +127,9 @@ func (b *Builder) processStateVariables(unit *ast.StateVariableDeclaration) *Sta // It could be that the name of the type name node is not set, but the type description string is. if variableNode.Type == "" { - if variableNode.TypeDescription == nil { - utils.DumpNodeWithExit(variableNode) - } + /* if variableNode.TypeDescription == nil { + utils.DumpNodeWithExit(variableNode) + }*/ variableNode.Type = variableNode.TypeDescription.TypeString } diff --git a/parser/solidity_parser.go b/parser/solidity_parser.go index e66e2be9..2f67aea5 100644 --- a/parser/solidity_parser.go +++ b/parser/solidity_parser.go @@ -25049,11 +25049,14 @@ func (p *SolidityParser) Sempred(localctx antlr.RuleContext, ruleIndex, predInde case 30: var t *StateVariableDeclarationContext = nil if localctx != nil { - if tCtx, ok := localctx.(*StateVariableDeclarationContext); ok { + if tCtx, ok := localctx.(*StateVariableDeclarationContext); ok { t = tCtx } else if _, ok := localctx.(*IdentifierPathContext); ok { return true + } else if _, ok := localctx.(*TypeNameContext); ok { + return true } + //fmt.Printf("RECEIVED LOCALCLX %T \n", localctx) } return p.StateVariableDeclaration_Sempred(t, predIndex) diff --git a/storage/reader.go b/storage/reader.go index 3dd02f56..9a03b437 100644 --- a/storage/reader.go +++ b/storage/reader.go @@ -3,7 +3,6 @@ package storage import ( "context" "fmt" - "github.com/unpackdev/solgo/utils" "strings" ) @@ -75,8 +74,9 @@ func (r *Reader) CalculateStorageLayout() error { for _, variable := range variables { storageSize, found := variable.GetAST().GetTypeName().StorageSize() if !found { - utils.DumpNodeWithExit(variable.GetAST().GetTypeName()) - return fmt.Errorf("error calculating storage size for variable: %s", variable.GetName()) + //utils.DumpNodeNoExit(variable.GetAST().GetTypeName()) + //return fmt.Errorf("error calculating storage size for variable: %s", variable.GetName()) + continue } typeName := variable.GetType()