solcover

package
v0.0.0-...-948650a Latest Latest
Warning

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

Go to latest
Published: Jan 25, 2024 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package solcover provides trace-based Solidity coverage analysis by mapping from EVM-trace program counters to original Solidity source code.

This package doesn't typically need to be used directly, and is automatically supported by adding the source-map flag to `ethier gen` of the github.com/divergencetech/ethier/ethier binary for generating Go bindings.

See https://docs.soliditylang.org/en/v0.8.14/internals/source_mappings.html for more information.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Collector

func Collector() (vm.EVMLogger, func() []byte)

Collector returns an EVMLogger that can be used to trace EVM operations for code coverage. The returned function returns an LCOV trace file at any time coverage is not being actively collected (i.e. it is not thread safe with respect to VM computation).

Coverage will only be collected for contracts registered with RegisterContract() before they are deployed; their respective code also must have been registered with RegisterSourceCode(…, isExternal = false).

func RegisterContract

func RegisterContract(name string, c *compiler.Contract, sourceList []string)

RegisterContract registers a compiled contract by its fully qualified name. This allows inspection of EVM traces to watch for contract deployments that are matched against already-registered contracts, and then for mapping each step in the trace back to original source code via the program counter. See SourceByName() documentation re fully qualified names.

The order of the sourceList MUST match the solc output from which the *Contract was parsed. The Contract's Info.SrcMapRuntime represents files as indices into this slice so a change in order will result in invalid results. All files included in sourceList SHOULD be registered via RegisterSourceCode before calling RegisterContract.

RegisterContract MUST be called before deployment otherwise RegisterDeployedContract will fail to match the byte code. This is typically done as part on an init() function, and `ethier gen` generated code performs this step automatically.

func RegisterDeployedContract

func RegisterDeployedContract(addr common.Address, code []byte)

RegisterDeployedContract matches the code against contracts registered with RegisterContract, allowing future calls to Source(addr, …) to return data pertaining to the correct contract.

RegisterDeployedContract should be called by EVMLogger.CaptureStart when the create flag is true, passing the deployment address and the input code bytes.

func RegisterSourceCode

func RegisterSourceCode(fileName, contents string, isExternal bool)

RegisterSourceCode registers the contents of source files passed in sourceList arguments to RegisterContract(). This allows op codes in contracts, deployed or otherwise, to be mapped back to the specific Solidity code that resulted in their compilation.

RegisterSourceCode SHOULD be called before all calls to RegisterContract that include fileName in the sourceList otherwise Location values will not contain line and column numbers. External source code, e.g. OpenZeppelin contracts, won't be monitored in coverage collection, but will be available for Etherscan verification.

Types

type JumpType

type JumpType string

A JumpType describes the action of a JUMP instruction.

const (
	FunctionIn  JumpType = `i`
	FunctionOut JumpType = `o`
	RegularJump JumpType = `-`
)

Possible JumpType values.

type Location

type Location struct {
	// InstructionNumber is the index of the instruction, within the runtime
	// byte code, that was compiled from this Solidity Location. Note that this
	// is different to the regular byte-code index (i.e. the program counter) as
	// PUSH<N> instructions use 1+N bytes. InstructionNumber is therefore
	// equivalent to a regular slice index after stripping the N pushed bytes
	// for each PUSH<N>.
	InstructionNumber int
	// OpCode is the instruction found at InstructionNumber.
	OpCode vm.OpCode

	// FileIdx refers to the index of the source file in the inputs to solc, as
	// returned in solc output, but can generally be ignored in favour of the
	// Source, which is determined from the SourceList parameter passed to
	// RegisterContract.
	FileIdx int
	// Source is the relative file path to the source that solc used to compile
	// this particular instruction from the location.
	Source string

	// Start and Length are byte offsets into Source, describing the specific
	// code from which this (and other) InstructionNumber locations were
	// compiled.
	Start, Length int

	// Line and Col are both 1-indexed as this is typical behaviour of IDEs and
	// coverage reports.
	Line, Col int
	// EndLine and EndCol are Length bytes after Line and Col, also 1-indexed.
	EndLine, EndCol int

	// Jump and ModifierDepth are the j and m elements, respectively, as
	// described in the Solidity source_mappings documentation above.
	Jump          JumpType
	ModifierDepth int
}

A Location is an offset-based location in a Solidity file. Using notation described in https://docs.soliditylang.org/en/v0.8.14/internals/source_mappings.html, s = Start, l = Length, f = FileIdx, j = Jump, and m = ModifierDepth.

Note that two Locations may have the same offset within the same file but their OpCode and instruction number will differ.

func Source

func Source(contract common.Address, pc uint64) (*Location, bool)

Source returns the code location that was compiled into the instruction at the specific program counter in the deployed contract. The contract's address MUST have been registered with RegisterDeployedContract().

func SourceByName

func SourceByName(contractName string, pc uint64) (*Location, bool)

SourceByName functions identically to Source but doesn't require that the contract has been deployed. The contract MUST have been registered with RegisterContract(). The contractName is fully qualified, including both the source file and the name, e.g. path/to/file.sol:ContractName.

NOTE that there isn't a one-to-one mapping between runtime byte code (i.e. program counter) and instruction number because the PUSH* instructions require additional bytes as documented in: https://docs.soliditylang.org/en/v0.8.14/internals/source_mappings.html.

Directories

Path Synopsis
Package srcmaptest is a test-only package of generated Solidity bindings used to test the ethier/solidity package.
Package srcmaptest is a test-only package of generated Solidity bindings used to test the ethier/solidity package.

Jump to

Keyboard shortcuts

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