solgo

package module
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2024 License: Apache-2.0 Imports: 18 Imported by: 11

README

Build Status Security Status Coverage Status Go Report Card License PkgGoDev Discord

Ethereum and Solidity Toolkit in Go: Parser, Analyzer, and Introspector

SolGo - a robust tool crafted in Go, designed to dissect and analyze Solidity's source code.

The parser is generated from a Solidity grammar file using Antlr, producing a lexer, parser, and listener using AntlrGo. This allows for the syntactic analysis of Solidity code, transforming it into a parse tree that offers offers a detailed syntactic representation of the code, allowing for intricate navigation and manipulation.

This project is ideal for those diving into data analysis, construction of robust APIs, developing advanced analysis tools, enhancing smart contract security, and anyone keen on harnessing Go for their Solidity endeavors.

Solidity Version Support

Currently, Solidity versions equal or higher to 0.6.0 are supported.

Older versions may or may not work due to changes in syntax that is not currently supported by the grammar file. In the future, we have plans to support all versions of Solidity.

Disclaimer

Please be aware that this project is still under active development. While it is approaching a state suitable for production use, there may still be undiscovered issues or limitations. Over the next few months, extensive testing will be conducted to evaluate its performance and stability. Additional tests and documentation will also be added during this phase. Additionally, most of the interfaces will stay as is, however, there could be architectural changes that may break your build in the future. I'll try to change as less as possible and notify everyone about the change in release notes.

Once I am confident that the project is fully ready for production, this disclaimer will be removed. Until then, please use the software with caution and report any potential issues or feedback to help improve its quality.

Documentation

The SolGo basic documentation is hosted on GitHub, ensuring it's always up-to-date with the latest changes and features. You can access the full documentation here.

Getting Started

Detailed examples of how to install and use this package can be found in the Usage section.

Solidity Language Grammar

Latest Solidity language grammar higher overview and detailed description can be found here.

ANTLR Grammar

We are using grammar files that are maintained by the Solidity team. Link to the grammar files can be found here.

ANTLR Go

We are using the ANTLR4 Go runtime library to generate the parser. Repository can be found here.

Crytic Slither

We are using Slither to detect vulnerabilities in smart contracts. Repository can be found here.

Makes no sense to rewrite all of that hard work just to be written in Go. Therefore, a bit of python will not hurt. In the future we may change direction.

Features

  • Protocol Buffers: Utilizing Protocol Buffers, SolGo offers a structured data format, paving the way for enhanced analysis and facilitating a unified interface for diverse tools. Currently, it supports Go and Javascript, with plans to incorporate Rust and Python in upcoming versions.
  • Abstract Syntax Tree (AST) Generation: Package ast is equipped with a dedicated builder that crafts an Abstract Syntax Tree (AST) tailored for Solidity code.
  • Intermediate Representation (IR) Generation: From the AST, SolGo is adept at generating an Intermediate Representation (IR). ir package serves as a language-neutral depiction of the contract, encapsulating pivotal components like functions, state variables, and events, thus broadening the scope for intricate analysis and contract manipulation.
  • Control Flow Graph (CFG) Generation: Building upon the IR, SolGo provides tools for constructing and visualizing Control Flow Graphs (CFGs) of Solidity contracts, aiding in the analysis of contract execution paths and potential bottlenecks.
  • Application Binary Interface (ABI) Generation: SolGo's in-built abi package can interpret contract definitions, enabling the generation of ABI for a collective group of contracts or individual ones.
  • Opcode Tools: The opcode package in SolGo demystifies bytecode by decompiling it into opcodes. Additionally, it provides tools for the creation and visualization of opcode execution trees, granting a holistic perspective of opcode sequences in smart contracts.
  • Library Integration: SolGo is programmed to autonomously source and assimilate Solidity contracts from renowned libraries, notably OpenZeppelin. This feature enables users to seamlessly import and utilize contracts from these libraries without the need for manual integration.
  • EIP & ERC Registry: SolGo introduces a package standards exclusively for Ethereum Improvement Proposals (EIPs) and Ethereum Request for Comments (ERCs). This package streamlines interactions with diverse contract standards by encompassing functions, events, and a registry system optimized for proficient management.
  • Solidity Compiler Detection & Compilation: SolGo intelligently identifies the Solidity version employed for contract compilation. This not only streamlines the process of determining the compiler version but also equips users with the capability to seamlessly compile contracts.
  • Security Audit Package: Prioritizing security, SolGo has incorporated an audit package. This specialized package leverages Slither's sophisticated algorithms to scrutinize and pinpoint potential vulnerabilities in Solidity smart contracts, ensuring robust protection against adversarial threats.
  • Contract Bytecode Validation: Enhanced validation package ensures the integrity and authenticity of contract bytecode. By comparing the bytecode of a deployed contract with the expected bytecode generated from its source code, SolGo can detect any discrepancies or potential tampering. This feature is crucial for verifying that a deployed contract's bytecode corresponds accurately to its source code, providing an added layer of security and trust for developers and users alike.

External Projects / Extensions

List of the projects that use SolGo:

  • Inspector - Tool for downloading, managing and inspecting smart contracts for Ethereum-based chains.

If you wish to add your repository to the list, make sure to submit new PR :)

Contributing

Contributions to SolGo are always welcome! Please visit Contributing for more information on how to get started.

License

SolGo is licensed under the Apache 2.0. See LICENSE for the full license text.

Documentation

Overview

Package solgo provides a suite of tools for parsing, analyzing, and interacting with Solidity contracts. It includes a contextual parser that maintains a stack of contexts as it parses a contract, allowing it to keep track of the current context (e.g., within a contract definition, function definition, etc.). It also includes a contract listener that extracts information about contracts as they are parsed, including the contract name, implemented interfaces, imported contracts, pragmas, and comments. Additionally, it includes a syntax error listener that listens for syntax errors in contracts and categorizes them by severity. The package also provides functionality for generating and working with Ethereum contract ABIs (Application Binary Interfaces). This includes parsing contract definitions to extract ABI information, normalizing type names, and handling complex types like mappings. These tools can be used together to provide a comprehensive interface for working with Solidity contracts, making it easier to understand their structure, identify potential issues, and interact with them on the Ethereum network.

Index

Constants

This section is empty.

Variables

View Source
var ErrPathFound = errors.New("path found")

Functions

This section is empty.

Types

type ListenerName

type ListenerName string

ListenerName represents the name of a listener.

const (
	ListenerAbi          ListenerName = "abi"
	ListenerContractInfo ListenerName = "contract_info"
	ListenerAst          ListenerName = "ast"
	ListenerSyntaxErrors ListenerName = "syntax_errors"
)

Predefined listener names.

func (ListenerName) String

func (l ListenerName) String() string

type Node

type Node struct {
	Name         string
	Size         int
	Content      string
	Dependencies []string
}

Node represents a unit of source code in Solidity with its dependencies.

type Parser

type Parser struct {
	// contains filtered or unexported fields
}

Parser is a struct that encapsulates the functionality for parsing and analyzing Solidity contracts.

func NewParser

func NewParser(ctx context.Context, input io.Reader) (*Parser, error)

New creates a new instance of SolGo. It takes a context and an io.Reader from which the Solidity contract is read. It initializes an input stream, lexer, token stream, and parser, and sets up error listeners.

func NewParserFromSources

func NewParserFromSources(ctx context.Context, sources *Sources) (*Parser, error)

NewParserFromSources creates a new instance of parser from a reader. It takes a context and an io.Reader from which the Solidity contract is read. It initializes an input stream, lexer, token stream, and parser, and sets up error listeners.

func (*Parser) GetAllListeners

func (s *Parser) GetAllListeners() map[ListenerName]antlr.ParseTreeListener

func (*Parser) GetContextualParser

func (s *Parser) GetContextualParser() *syntaxerrors.ContextualParser

GetContextualParser returns the ContextualParser which wraps the Solidity parser.

func (*Parser) GetInput

func (s *Parser) GetInput() io.Reader

GetInput returns the raw input reader from which the Solidity contract is read.

func (*Parser) GetInputStream

func (s *Parser) GetInputStream() *antlr.InputStream

GetInputStream returns the ANTLR input stream which is used by the lexer.

func (*Parser) GetLexer

func (s *Parser) GetLexer() *parser.SolidityLexer

GetLexer returns the Solidity lexer which tokenizes the input stream.

func (*Parser) GetListener

func (s *Parser) GetListener(name ListenerName) (antlr.ParseTreeListener, error)

func (*Parser) GetParser

func (s *Parser) GetParser() *parser.SolidityParser

GetParser returns the Solidity parser which parses the token stream.

func (*Parser) GetSources

func (s *Parser) GetSources() *Sources

GetSources returns the sources of the Solidity contract.

func (*Parser) GetTokenStream

func (s *Parser) GetTokenStream() *antlr.CommonTokenStream

GetTokenStream returns the stream of tokens produced by the lexer.

func (*Parser) GetTree

func (s *Parser) GetTree() antlr.ParseTree

GetTree returns the root of the parse tree that results from parsing the Solidity contract.

func (*Parser) IsListenerRegistered

func (s *Parser) IsListenerRegistered(name ListenerName) bool

func (*Parser) Parse

func (s *Parser) Parse() []syntaxerrors.SyntaxError

Parse initiates the parsing process. It walks the parse tree with all registered listeners and returns any syntax errors that were encountered during parsing.

func (*Parser) RegisterListener

func (s *Parser) RegisterListener(name ListenerName, listener antlr.ParseTreeListener) error

type SourceUnit

type SourceUnit struct {
	Name    string `yaml:"name" json:"name"`
	Path    string `yaml:"path" json:"path"`
	Content string `yaml:"content" json:"content"`
}

SourceUnit represents a unit of source code in Solidity. It includes the name, path, and content of the source code.

func (*SourceUnit) GetBasePath added in v0.3.1

func (s *SourceUnit) GetBasePath() string

GetBasePath returns the base path of the SourceUnit.

func (*SourceUnit) GetContent

func (s *SourceUnit) GetContent() string

GetContent returns the content of the SourceUnit.

func (*SourceUnit) GetName

func (s *SourceUnit) GetName() string

GetName returns the name of the SourceUnit.

func (*SourceUnit) GetPath

func (s *SourceUnit) GetPath() string

GetPath returns the path of the SourceUnit.

func (*SourceUnit) String

func (s *SourceUnit) String() string

String returns a string representation of the SourceUnit.

func (*SourceUnit) ToProto

func (s *SourceUnit) ToProto() *sources_pb.SourceUnit

ToProto converts a SourceUnit to a protocol buffer SourceUnit.

type Sources

type Sources struct {
	SourceUnits          []*SourceUnit `yaml:"source_units" json:"source_units"`
	EntrySourceUnitName  string        `yaml:"entry_source_unit" json:"base_source_unit"`
	LocalSources         bool          `yaml:"local_sources" json:"local_sources"`
	MaskLocalSourcesPath bool          `yaml:"mask_local_sources_path" json:"mask_local_sources_path"`
	LocalSourcesPath     string        `yaml:"local_sources_path" json:"local_sources_path"`
	// contains filtered or unexported fields
}

Sources represent a collection of SourceUnit. It includes a slice of SourceUnit and the name of the entry source unit.

func NewSourcesFromEtherScan

func NewSourcesFromEtherScan(entryContractName string, sc interface{}) (*Sources, error)

NewSourcesFromEtherScan creates a Sources from an EtherScan response. This is a helper function that ensures easier integration when working with the EtherScan provider. This includes BscScan, and other equivalent from the same family.

func NewSourcesFromMetadata

func NewSourcesFromMetadata(md *metadata.ContractMetadata) *Sources

NewSourcesFromMetadata creates a Sources from a metadata package ContractMetadata. This is a helper function that ensures easier integration when working with the metadata package.

func NewSourcesFromPath added in v0.3.2

func NewSourcesFromPath(entrySourceUnitName, path string) (*Sources, error)

func NewSourcesFromProto added in v0.3.2

func NewSourcesFromProto(entryContractName string, sc *sources_pb.Sources) (*Sources, error)

func (*Sources) AppendSource added in v0.3.1

func (s *Sources) AppendSource(source *SourceUnit)

AppendSource appends a SourceUnit to the Sources. If a SourceUnit with the same name already exists, it replaces it unless the new SourceUnit has less content.

func (*Sources) ArePrepared

func (s *Sources) ArePrepared() bool

ArePrepared returns true if the Sources has been prepared.

func (*Sources) GetCombinedSource

func (s *Sources) GetCombinedSource() string

GetCombinedSource combines the content of all SourceUnits in the Sources into a single string, separated by two newlines.

func (*Sources) GetLocalSource

func (s *Sources) GetLocalSource(partialPath string, relativeTo string) (*SourceUnit, error)

GetLocalSource attempts to find a local source file that matches the given partial path. It searches relative to the provided path and returns a SourceUnit representing the found source. If no matching source is found, it returns nil.

The function replaces any instance of "@openzeppelin" in the partial path with the actual path to the openzeppelin-contracts repository. It then walks the file tree starting from "./sources/", checking each file against the new path.

If the new path contains "../", it removes this and looks for the file in the parent directory. If a match is found, it creates a new SourceUnit with the name and path of the file, and returns it.

If no "../" is present in the new path, it simply creates a new SourceUnit with the name and path.

After a SourceUnit is created, the function checks if the file at the path exists. If it does, it reads the file content and assigns it to the SourceUnit's Content field. If the file does not exist, it returns an error.

If the walk function encounters an error other than ErrPathFound, it returns the error. If the source is still nil after the walk, it returns nil.

func (*Sources) GetSolidityVersion

func (s *Sources) GetSolidityVersion() (string, error)

GetSolidityVersion extracts the highest Solidity version from all source units.

func (*Sources) GetSourceUnitByName

func (s *Sources) GetSourceUnitByName(name string) *SourceUnit

GetSourceUnitByName returns the SourceUnit with the given name from the Sources. If no such SourceUnit exists, it returns nil.

func (*Sources) GetSourceUnitByNameAndSize

func (s *Sources) GetSourceUnitByNameAndSize(name string, size int) *SourceUnit

GetSourceUnitByNameAndSize returns the SourceUnit with the given name and size from the Sources. If no such SourceUnit exists, it returns nil.

func (*Sources) GetSourceUnitByPath

func (s *Sources) GetSourceUnitByPath(path string) *SourceUnit

GetSourceUnitByPath returns the SourceUnit with the given path from the Sources. If no such SourceUnit exists, it returns nil.

func (*Sources) GetUnits

func (s *Sources) GetUnits() []*SourceUnit

GetUnits returns the SourceUnits in the Sources.

func (*Sources) HasUnits

func (s *Sources) HasUnits() bool

HasUnits returns true if the Sources has at least one SourceUnit.

func (*Sources) Prepare

func (s *Sources) Prepare() error

Prepare validates and prepares the Sources. It checks if each SourceUnit has either a path or content and a name. If a SourceUnit has a path but no content, it reads the content from the file at the path.

func (*Sources) ReplaceSource added in v0.3.1

func (s *Sources) ReplaceSource(old *SourceUnit, newSource *SourceUnit)

ReplaceSource replaces an old SourceUnit with a new one. If the old SourceUnit is not found, nothing happens.

func (*Sources) SortContracts

func (s *Sources) SortContracts() error

SortContracts sorts the SourceUnits based on their dependencies.

func (*Sources) SourceUnitExists

func (s *Sources) SourceUnitExists(name string) bool

SourceUnitExists returns true if a SourceUnit with the given name exists in the Sources.

func (*Sources) SourceUnitExistsIn

func (s *Sources) SourceUnitExistsIn(name string, units []*SourceUnit) bool

SourceUnitExistsIn returns true if a SourceUnit with the given name exists in the given slice of SourceUnits.

func (*Sources) SourceUnitPathExists added in v0.3.2

func (s *Sources) SourceUnitPathExists(name string) bool

SourceUnitExists returns true if a SourceUnit with the given name exists in the Sources.

func (*Sources) SourceUnitPathExistsIn added in v0.3.2

func (s *Sources) SourceUnitPathExistsIn(name string, units []*SourceUnit) bool

SourceUnitExistsIn returns true if a SourceUnit with the given name exists in the given slice of SourceUnits.

func (*Sources) ToProto

func (s *Sources) ToProto() *sources_pb.Sources

ToProto converts a Sources to a protocol buffer Sources.

func (*Sources) TruncateDir

func (s *Sources) TruncateDir(path string) error

TruncateDir removes all files and subdirectories within the specified directory.

func (*Sources) Validate

func (s *Sources) Validate() error

Validate checks the integrity of the Sources object. It ensures that: - There is at least one SourceUnit. - Each SourceUnit has a name and either a path or content. - If a SourceUnit has a path, the file at that path exists. - The entry source unit name is valid.

func (*Sources) WriteToDir

func (s *Sources) WriteToDir(path string) error

WriteToDir writes each SourceUnit's content to a file in the specified directory.

Directories

Path Synopsis
Package abi provides functionality for parsing and manipulating Solidity contract ABIs (Application Binary Interfaces).
Package abi provides functionality for parsing and manipulating Solidity contract ABIs (Application Binary Interfaces).
The package is designed to be flexible and adaptable to various Ethereum-compatible networks like Ethereum mainnet, Binance Smart Chain (BSC), and Polygon.
The package is designed to be flexible and adaptable to various Ethereum-compatible networks like Ethereum mainnet, Binance Smart Chain (BSC), and Polygon.
Package ast provides an Abstract Syntax Tree (AST) representation for Solidity contracts.
Package ast provides an Abstract Syntax Tree (AST) representation for Solidity contracts.
Package audit provides a comprehensive suite of tools for auditing smart contracts.
Package audit provides a comprehensive suite of tools for auditing smart contracts.
Package bindings abstracts the complexity of interacting with smart contracts deployed on the Ethereum blockchain and potentially other compatible networks.
Package bindings abstracts the complexity of interacting with smart contracts deployed on the Ethereum blockchain and potentially other compatible networks.
Package bytecode provides tools for decoding and analyzing Ethereum contract, transaction, events, and log bytecode.
Package bytecode provides tools for decoding and analyzing Ethereum contract, transaction, events, and log bytecode.
Package cfg provides structures and functions for building and manipulating control flow graphs (CFGs) of Solidity contracts.
Package cfg provides structures and functions for building and manipulating control flow graphs (CFGs) of Solidity contracts.
Package clients provides tools for managing and interacting with Ethereum clients.
Package clients provides tools for managing and interacting with Ethereum clients.
Package integrates various Ethereum-related functionalities including interaction with blockchain clients, fetching contract metadata from external providers such as etherscan, token discovery, bytecode validation, auditing, etc...
Package integrates various Ethereum-related functionalities including interaction with blockchain clients, fetching contract metadata from external providers such as etherscan, token discovery, bytecode validation, auditing, etc...
Package detector provides helpers for accessing solgo packages.
Package detector provides helpers for accessing solgo packages.
Package ir provides an intermediate representation of the AST.
Package ir provides an intermediate representation of the AST.
Package metadata provides functionality for interacting with IPFS/SWARM and retrieving contract metadata.
Package metadata provides functionality for interacting with IPFS/SWARM and retrieving contract metadata.
Package observers provides tools for managing and interacting with Ethereum onchain data such as blocks, transactions, events and logs.
Package observers provides tools for managing and interacting with Ethereum onchain data such as blocks, transactions, events and logs.
Package opcode offers tools for constructing and visualizing opcode execution trees, representing sequences of instructions.
Package opcode offers tools for constructing and visualizing opcode execution trees, representing sequences of instructions.
providers
bitquery
Package bitquery provides functions to query blockchain contract creation information using the Ethereum blockchain.
Package bitquery provides functions to query blockchain contract creation information using the Ethereum blockchain.
etherscan
Package etherscan provides a client for interacting with Etherscan's API, enabling the retrieval of blockchain data and supporting rate-limited API key rotation.
Package etherscan provides a client for interacting with Etherscan's API, enabling the retrieval of blockchain data and supporting rate-limited API key rotation.
Package standards provides structures and functions to represent and manipulate Ethereum Improvement Proposals (EIPs) and Ethereum standards.
Package standards provides structures and functions to represent and manipulate Ethereum Improvement Proposals (EIPs) and Ethereum standards.
Package storage provides tools for interacting with smart contract storages on the Ethereum based networks.
Package storage provides tools for interacting with smart contract storages on the Ethereum based networks.
Package syntaxerrors provides tools for detecting and handling syntax errors in Solidity contracts.
Package syntaxerrors provides tools for detecting and handling syntax errors in Solidity contracts.
Package tokens provides a high-level abstraction for interacting with Ethereum tokens.
Package tokens provides a high-level abstraction for interacting with Ethereum tokens.
Package validation provides utilities for verifying Ethereum based smart contracts.
Package validation provides utilities for verifying Ethereum based smart contracts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL