Example #1
0
 private void TopologicalSortImpl(HashSet <ContractDefinition> visited, ContractDefinition contract, List <ContractDefinition> result)
 {
     visited.Add(contract);
     foreach (int id in contract.ContractDependencies)
     {
         ContractDefinition dependency = context.GetASTNodeById(id) as ContractDefinition;
         Debug.Assert(dependency != null);
         if (!visited.Contains(dependency))
         {
             TopologicalSortImpl(visited, dependency, result);
         }
     }
     if (AllDependenciesVisited(visited, contract))
     {
         result.Add(contract);
     }
 }
        public static bool IsExternalFunctionCall(TranslatorContext context, FunctionCall node)
        {
            if (node.Expression is MemberAccess memberAccess)
            {
                if (memberAccess.Expression is Identifier identifier)
                {
                    if (identifier.Name == "this")
                    {
                        return(true);
                    }

                    if (identifier.Name == "super")
                    {
                        return(true);
                    }

                    if (!context.HasASTNodeId(identifier.ReferencedDeclaration))
                    {
                        return(true);
                    }

                    var contract = context.GetASTNodeById(identifier.ReferencedDeclaration) as ContractDefinition;
                    if (contract == null)
                    {
                        return(true);
                    }
                }
                else if (memberAccess.Expression is MemberAccess structSelect)
                {
                    //a.b.c.foo(...)
                    //TODO: do we want to check that the contract the struct variable is declared
                    // is not in the "context"? Why this isn't done for IndexAccess?
                    return(true);
                }
                else if (memberAccess.Expression.ToString().Equals("msg.sender"))
                {
                    // calls can be of the form "msg.sender.call()" or "msg.sender.send()" or "msg.sender.transfer()"
                    return(true);
                }
                else if (memberAccess.Expression is FunctionCall)
                {
                    // TODO: example?
                    return(true);
                }
                else if (memberAccess.Expression is IndexAccess)
                {
                    //a[i].foo(..)
                    return(true);
                }
                else if (memberAccess.Expression is TupleExpression)
                {
                    return(true);
                }
            }
            return(false);
        }
Example #3
0
 public void Collect()
 {
     foreach (ContractDefinition contract in context.ContractDefinitions)
     {
         foreach (int baseId in contract.LinearizedBaseContracts)
         {
             ContractDefinition baseContract = context.GetASTNodeById(baseId) as ContractDefinition;
             Debug.Assert(baseContract != null);
             context.AddSubTypeToContract(baseContract, contract);
         }
     }
 }
        private void ResolveFunctions()
        {
            ResolutionHelper          resolutionHelper = new ResolutionHelper(context);
            List <ContractDefinition> sortedContracts  = resolutionHelper.TopologicalSortByDependency(context.ContractDefinitions);

            foreach (ContractDefinition contract in sortedContracts)
            {
                // create a deep copy
                List <int> linearizedBaseContractIds = new List <int>(contract.LinearizedBaseContracts);
                linearizedBaseContractIds.Reverse();

                foreach (int id in linearizedBaseContractIds)
                {
                    ContractDefinition baseContract = context.GetASTNodeById(id) as ContractDefinition;
                    Debug.Assert(baseContract != null);

                    if (baseContract == contract)
                    {
                        HashSet <FunctionDefinition> functions = context.GetFuncDefintionsInContract(contract);
                        foreach (FunctionDefinition function in functions)
                        {
                            string signature = TransUtils.ComputeFunctionSignature(function);
                            context.AddFunctionToDynamicType(signature, contract, function);
                        }
                    }
                    else
                    {
                        HashSet <FunctionDefinition> functions = context.GetFuncDefintionsInContract(baseContract);
                        foreach (FunctionDefinition function in functions)
                        {
                            if (function.Visibility == EnumVisibility.PRIVATE)
                            {
                                continue;
                            }

                            string signature = TransUtils.ComputeFunctionSignature(function);
                            context.AddFunctionToDynamicType(signature, contract, function);
                        }
                        // Events
                        // TODO: Do we need to lookup by signature?
                        HashSet <EventDefinition> events = context.GetEventDefintionsInContract(baseContract);
                        foreach (var evt in events)
                        {
                            context.AddEventToContract(contract, evt);
                        }
                    }
                }
            }

            // PrintFunctionResolutionMap();
        }
        public static ContractDefinition GetStaticDispatchingContract(TranslatorContext context, FunctionCall node)
        {
            VeriSolAssert(node.Expression is MemberAccess);
            MemberAccess memberAccess = node.Expression as MemberAccess;

            Identifier contractId = memberAccess.Expression as Identifier;

            VeriSolAssert(contractId != null, $"Unknown contract name: {memberAccess.Expression}");

            ContractDefinition contract = context.GetASTNodeById(contractId.ReferencedDeclaration) as ContractDefinition;

            VeriSolAssert(contract != null);
            return(contract);
        }
 public static bool IsStaticDispatching(TranslatorContext context, FunctionCall node)
 {
     if (node.Expression is MemberAccess memberAccess)
     {
         if (memberAccess.Expression is Identifier ident)
         {
             if (context.GetASTNodeById(ident.ReferencedDeclaration) is ContractDefinition)
             {
                 return(true);
             }
         }
     }
     return(false);
 }
 public static ContractDefinition IsLibraryFunctionCall(TranslatorContext context, FunctionCall node)
 {
     if (node.Expression is MemberAccess memberAccess)
     {
         if (memberAccess.Expression is Identifier identifier)
         {
             var contract = context.GetASTNodeById(identifier.ReferencedDeclaration) as ContractDefinition;
             // a Library is treated as an external function call
             // we need to do it here as the Lib.Foo, Lib is not an expression but name of a contract
             if (contract.ContractKind == EnumContractKind.LIBRARY)
             {
                 return(contract);
             }
         }
     }
     return(null);
 }
        private void ResolveStateVariables()
        {
            ResolutionHelper          resolutionHelper = new ResolutionHelper(context);
            List <ContractDefinition> sortedContracts  = resolutionHelper.TopologicalSortByDependency(context.ContractDefinitions);

            foreach (ContractDefinition contract in sortedContracts)
            {
                // create a deep copy
                List <int> linearizedBaseContractIds = new List <int>(contract.LinearizedBaseContracts);
                linearizedBaseContractIds.Reverse();

                foreach (int id in linearizedBaseContractIds)
                {
                    ContractDefinition baseContract = context.GetASTNodeById(id) as ContractDefinition;
                    Debug.Assert(baseContract != null);

                    if (baseContract == contract)
                    {
                        HashSet <VariableDeclaration> stateVars = context.GetStateVarsByContract(contract);
                        foreach (VariableDeclaration stateVar in stateVars)
                        {
                            string name = stateVar.Name;
                            context.AddStateVarToDynamicType(name, contract, stateVar);
                        }
                    }
                    else
                    {
                        HashSet <VariableDeclaration> stateVars = context.GetStateVarsByContract(baseContract);
                        foreach (VariableDeclaration stateVar in stateVars)
                        {
                            if (stateVar.Visibility == EnumVisibility.PRIVATE)
                            {
                                continue;
                            }

                            string name = stateVar.Name;
                            context.AddStateVarToDynamicType(name, contract, stateVar);
                        }
                    }
                }
            }

            // PrintStateVarResolutionMap();
        }
Example #9
0
        public static string InferFunctionSignature(TranslatorContext context, FunctionCall node,
                                                    bool forceNameLookup = false)
        {
            Debug.Assert(node.Arguments != null);

            if (!forceNameLookup && node.Expression is MemberAccess memberAccess)
            {
                Debug.Assert(memberAccess.ReferencedDeclaration != null);
                FunctionDefinition function = context.GetASTNodeById(memberAccess.ReferencedDeclaration.Value) as FunctionDefinition;
                Debug.Assert(function != null, $"Could not find function {node.ToString()}");
                StringBuilder builder = new StringBuilder();
                builder.Append(function.Name).Append("(");
                if (function.Parameters.Parameters != null && function.Parameters.Parameters.Count > 0)
                {
                    foreach (VariableDeclaration varDecl in function.Parameters.Parameters)
                    {
                        //builder.Append(varDecl.TypeDescriptions.TypeString).Append(", ");
                        builder.Append(InferTypeFromTypeString(varDecl.TypeDescriptions.TypeString)).Append(", ");
                    }
                    builder.Length -= 2;
                }
                builder.Append(")");
                return(builder.ToString());
            }
            else
            {
                string        functionName = GetFuncNameFromFuncCall(node);
                StringBuilder builder      = new StringBuilder();
                builder.Append(functionName).Append("(");
                if (node.Arguments.Count > 0)
                {
                    foreach (Expression argument in node.Arguments)
                    {
                        string typeString = InferTypeFromTypeString(argument.TypeDescriptions.TypeString);
                        builder.Append(typeString).Append(", ");
                    }
                    builder.Length -= 2;
                }
                builder.Append(")");
                return(builder.ToString());
            }
        }
Example #10
0
        public static string InferFunctionSignature(TranslatorContext context, FunctionCall node)
        {
            Debug.Assert(node.Arguments != null);

            if (node.Expression is MemberAccess memberAccess)
            {
                Debug.Assert(memberAccess.ReferencedDeclaration != null);
                FunctionDefinition function = context.GetASTNodeById(memberAccess.ReferencedDeclaration.Value) as FunctionDefinition;
                Debug.Assert(function != null, $"Could not find function {node.ToString()}");
                StringBuilder builder = new StringBuilder();
                builder.Append(function.Name).Append("(");
                if (function.Parameters.Parameters != null && function.Parameters.Parameters.Count > 0)
                {
                    foreach (VariableDeclaration varDecl in function.Parameters.Parameters)
                    {
                        builder.Append(varDecl.TypeDescriptions.TypeString).Append(", ");
                    }
                    builder.Length -= 2;
                }
                builder.Append(")");
                return(builder.ToString());
            }
            else
            {
                string        functionName = GetFuncNameFromFunctionCall(node);
                StringBuilder builder      = new StringBuilder();
                builder.Append(functionName).Append("(");
                if (node.Arguments.Count > 0)
                {
                    foreach (Expression argument in node.Arguments)
                    {
                        string typeString = argument.TypeDescriptions.TypeString;
                        if (typeString.StartsWith("int_const"))
                        {
                            typeString = "int256";
                        }
                        if (typeString.StartsWith("uint_const"))
                        {
                            typeString = "int256";
                        }
                        if (typeString.StartsWith("string") || typeString.StartsWith("literal_string"))
                        {
                            typeString = "string";
                        }
                        if (typeString.StartsWith("bytes "))
                        {
                            typeString = "bytes";           //"bytes storage ref"
                        }
                        if (typeString.Contains(" memory")) //"struct Foo memory"
                        {
                            typeString = typeString.Substring(0, typeString.IndexOf(" memory"));
                        }
                        if (typeString.Contains(" storage"))
                        {
                            typeString = typeString.Substring(0, typeString.IndexOf(" storage"));
                        }
                        builder.Append(typeString).Append(", ");
                    }
                    builder.Length -= 2;
                }
                builder.Append(")");
                return(builder.ToString());
            }
        }
        public ERC20SpecGenerator(TranslatorContext context, AST solidityAST, String entryPoint)
        {
            this.context      = context;
            this.solidityAST  = solidityAST;
            varDecls          = new Dictionary <string, VariableDeclaration>();
            fnContracts       = new Dictionary <string, ContractDefinition>();
            otherVars         = new List <VariableDeclaration>();
            declToContractInd = new Dictionary <VariableDeclaration, int>();

            foreach (ContractDefinition def in context.ContractDefinitions)
            {
                if (def.Name.Equals(entryPoint))
                {
                    entryContract = def;
                }
            }

            int contractInd = 0;

            foreach (int id in entryContract.LinearizedBaseContracts)
            {
                contractInd++;
                ContractDefinition contract = context.GetASTNodeById(id) as ContractDefinition;

                if (context.ContractToStateVarsMap.ContainsKey(contract))
                {
                    otherVars.AddRange(context.ContractToStateVarsMap[contract]);
                    foreach (VariableDeclaration decl in context.ContractToStateVarsMap[contract])
                    {
                        declToContractInd[decl] = contractInd;
                    }
                }

                if (!context.ContractToFunctionsMap.ContainsKey(contract))
                {
                    continue;
                }

                HashSet <FunctionDefinition> fnDefs = context.ContractToFunctionsMap[contract];

                foreach (FunctionDefinition fnDef in fnDefs)
                {
                    if (ERC20fns.Contains(fnDef.Name) && !fnContracts.ContainsKey(fnDef.Name))
                    {
                        fnContracts[fnDef.Name] = contract;
                    }

                    if (ERC20Vars.Contains(fnDef.Name) && !varDecls.ContainsKey(fnDef.Name))
                    {
                        ReturnDeclarationFinder declFinder = new ReturnDeclarationFinder(context);
                        VariableDeclaration     decl       = declFinder.findDecl(contract, fnDef);

                        if (decl != null)
                        {
                            varDecls[fnDef.Name] = decl;
                        }
                    }
                }
            }

            foreach (VariableDeclaration decl in varDecls.Values)
            {
                otherVars.Remove(decl);
            }

            otherVars.RemoveAll(v => v.Constant);
        }
        public static ContractDefinition GetUsedLibrary(TranslatorContext context, ContractDefinition curContract,
                                                        MemberAccess memberAccess)
        {
            FunctionDefinition fnDef = context.GetASTNodeById(memberAccess.ReferencedDeclaration.Value) as FunctionDefinition;

            if (fnDef == null || !context.FunctionToContractMap.ContainsKey(fnDef))
            {
                return(null);
            }

            ContractDefinition fnContract = context.GetContractByFunction(fnDef);

            Dictionary <ContractDefinition, UserDefinedTypeName> usingLibs = new Dictionary <ContractDefinition, UserDefinedTypeName>();
            List <int> contractIds = new List <int>();

            contractIds.Add(curContract.Id);
            contractIds.AddRange(curContract.LinearizedBaseContracts);

            foreach (int id in contractIds)
            {
                ContractDefinition baseContract = context.GetASTNodeById(id) as ContractDefinition;

                foreach (UserDefinedTypeName typeName in context.UsingMap[baseContract].Keys)
                {
                    ContractDefinition libDef = context.GetASTNodeById(typeName.ReferencedDeclaration) as ContractDefinition;
                    if (!usingLibs.ContainsKey(libDef))
                    {
                        usingLibs[libDef] = typeName;
                    }
                }
            }

            if (usingLibs.ContainsKey(fnContract))
            {
                if (memberAccess.Expression.TypeDescriptions.IsContract() &&
                    !memberAccess.Expression.TypeDescriptions.IsArray())
                {
                    //search sub-types
                    UserDefinedTypeName libType = usingLibs[fnContract];
                    String                       contractName = memberAccess.Expression.TypeDescriptions.TypeString.Split(" ")[1];
                    ContractDefinition           contractDef  = context.GetContractByName(contractName);
                    HashSet <ContractDefinition> usedBy       = context.UsingMap[curContract][libType].FindAll(t =>
                                                                                                               t is UserDefinedTypeName u &&
                                                                                                               context.GetASTNodeById(u.ReferencedDeclaration) is ContractDefinition).Select(c =>
                                                                                                                                                                                             context.GetASTNodeById(((UserDefinedTypeName)(c))
                                                                                                                                                                                                                    .ReferencedDeclaration) as ContractDefinition).ToHashSet();

                    bool usesLib = usedBy.Contains(contractDef);

                    foreach (int id in contractDef.LinearizedBaseContracts)
                    {
                        ContractDefinition baseContract = context.GetASTNodeById(id) as ContractDefinition;
                        if (usedBy.Contains(baseContract))
                        {
                            usesLib = true;
                        }
                    }

                    return(usesLib ? fnContract : null);
                }
                else
                {
                    return(fnContract);
                }
            }

            return(null);
        }
        public FunctionDependencyCollector(TranslatorContext context, String baseContractName, HashSet <String> fnNames)
        {
            this.context = context;
            nameToFn     = new Dictionary <String, List <FunctionDefinition> >();
            fnDeps       = new HashSet <FunctionDefinition>();
            modDeps      = new HashSet <ModifierDefinition>();
            seenFns      = new HashSet <FunctionDefinition>();
            worklist     = new LinkedList <FunctionDefinition>();
            ContractDefinition baseContract = null;

            foreach (ContractDefinition def in context.ContractDefinitions)
            {
                if (def.Name.Equals(baseContractName))
                {
                    baseContract = def;
                }

                if (context.ContractToFunctionsMap.ContainsKey(def))
                {
                    foreach (FunctionDefinition fnDef in context.ContractToFunctionsMap[def])
                    {
                        if (nameToFn.ContainsKey(fnDef.Name))
                        {
                            nameToFn[fnDef.Name].Add(fnDef);
                        }
                        else
                        {
                            nameToFn[fnDef.Name] = new List <FunctionDefinition>()
                            {
                                fnDef
                            };
                        }
                    }
                }
            }

            foreach (FunctionDefinition fnDef in context.GetVisibleFunctionsByContract(baseContract))
            {
                if (fnNames.Contains(fnDef.Name))
                {
                    worklist.AddLast(fnDef);
                    seenFns.Add(fnDef);
                }
            }

            while (worklist.Count != 0)
            {
                curFn = worklist.First.Value;
                worklist.RemoveFirst();
                fnDeps.Add(curFn);

                if (curFn.Modifiers != null)
                {
                    foreach (ModifierInvocation mod in curFn.Modifiers)
                    {
                        int     id   = mod.ModifierName.ReferencedDeclaration;
                        ASTNode node = context.GetASTNodeById(id);

                        if (node is ModifierDefinition modDef)
                        {
                            if (!modDeps.Contains(modDef))
                            {
                                modDeps.Add(modDef);
                                modDef.Body.Accept(this);
                            }
                        }
                        else
                        {
                            throw new Exception("Modifier id does not reference a modifier declaration");
                        }
                    }
                }

                if (curFn.Body != null)
                {
                    curFn.Body.Accept(this);
                }
            }
        }