• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

unpackdev / solgo / 8960975808

05 May 2024 08:34PM UTC coverage: 64.769% (-0.3%) from 65.065%
8960975808

push

github

web-flow
Opcode functions and instruction tree + JSON normalization (#210)

245 of 449 new or added lines in 61 files covered. (54.57%)

2 existing lines in 1 file now uncovered.

27471 of 42414 relevant lines covered (64.77%)

0.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

24.29
/opcode/matcher.go
1
package opcode
2

3
import (
4
        "bytes"
5
        "fmt"
6
        "strings"
7

8
        "github.com/ethereum/go-ethereum/common"
9
)
10

11
// MatchFunctionSignature checks if a given function signature matches any of the decompiled instructions.
12
func (d *Decompiler) MatchFunctionSignature(signature string) bool {
1✔
13
        // Remove "0x" prefix if present
1✔
14
        signature = strings.TrimPrefix(signature, "0x")
1✔
15

1✔
16
        for _, instruction := range d.instructions {
2✔
17
                if instruction.OpCode == CALL && len(instruction.Args) >= 4 {
2✔
18
                        functionSig := common.Bytes2Hex(instruction.Args[:4])
1✔
19
                        if functionSig == signature {
2✔
20
                                return true
1✔
21
                        }
1✔
22
                }
23
        }
24
        return false
1✔
25
}
26

27
func (d *Decompiler) MatchInstruction(instruction Instruction) bool {
1✔
28
        for _, inst := range d.instructions {
2✔
29
                if inst.Offset == instruction.Offset && inst.OpCode == instruction.OpCode && bytes.Equal(inst.Args, instruction.Args) {
2✔
30
                        return true
1✔
31
                }
1✔
32
        }
33
        return false
1✔
34
}
35

36
// GetStateVariables returns the instruction trees for all state variables declared in the bytecode.
NEW
37
func (d *Decompiler) GetStateVariables() ([]*InstructionTree, error) {
×
NEW
38
        // Initialize slice to hold state variable trees with estimated capacity
×
NEW
39
        stateVariables := make([]*InstructionTree, 0)
×
NEW
40

×
NEW
41
        // Iterate through instructions to find state variable declarations
×
NEW
42
        for _, instruction := range d.instructions {
×
NEW
43
                // Check if the instruction is a state variable declaration
×
NEW
44
                if d.isStateVariableDeclaration(instruction) {
×
NEW
45
                        // Build instruction tree for the state variable declaration
×
NEW
46
                        tree := NewInstructionTree(instruction)
×
NEW
47
                        stateVariables = append(stateVariables, tree)
×
NEW
48
                }
×
49
        }
50

NEW
51
        return stateVariables, nil
×
52
}
53

54
// Function to determine if an instruction declares a state variable
NEW
55
func (d *Decompiler) isStateVariableDeclaration(instruction Instruction) bool {
×
NEW
56
        // Check if the instruction is a PUSH operation followed by a SSTORE operation
×
NEW
57
        if instruction.OpCode.IsPush() && instruction.Offset+1 < len(d.instructions) {
×
NEW
58
                nextInstruction := d.instructions[instruction.Offset+1]
×
NEW
59
                if nextInstruction.OpCode == SSTORE {
×
NEW
60
                        return true
×
NEW
61
                }
×
62
        }
NEW
63
        return false
×
64
}
65

66
// GetEvents returns the instruction trees for all events declared in the bytecode.
NEW
67
func (d *Decompiler) GetEvents() ([]*InstructionTree, error) {
×
NEW
68
        // Initialize slice to hold event trees with estimated capacity
×
NEW
69
        events := make([]*InstructionTree, 0)
×
NEW
70

×
NEW
71
        // Iterate through instructions to find event definitions
×
NEW
72
        for _, instruction := range d.instructions {
×
NEW
73
                // Check if the instruction is an event definition
×
NEW
74
                if isEventDefinition(instruction) {
×
NEW
75
                        // Parse event arguments
×
NEW
76
                        args, err := parseEventArguments(instruction)
×
NEW
77
                        if err != nil {
×
NEW
78
                                return nil, fmt.Errorf("error parsing event arguments: %v", err)
×
NEW
79
                        }
×
80

81
                        // Build instruction tree for the event definition with arguments
NEW
82
                        tree := NewInstructionTree(instruction)
×
NEW
83
                        tree.Instruction.Args = args // Append event arguments
×
NEW
84
                        events = append(events, tree)
×
85
                }
86
        }
87

NEW
88
        return events, nil
×
89
}
90

91
// Function to determine if an instruction declares an event
NEW
92
func isEventDefinition(instruction Instruction) bool {
×
NEW
93
        // Check if the instruction is a LOG operation
×
NEW
94
        return instruction.OpCode == LOG0 || instruction.OpCode == LOG1 ||
×
NEW
95
                instruction.OpCode == LOG2 || instruction.OpCode == LOG3 || instruction.OpCode == LOG4
×
NEW
96
}
×
97

98
// Function to parse event arguments from instruction
NEW
99
func parseEventArguments(instruction Instruction) ([]byte, error) {
×
NEW
100
        // Check if the instruction has arguments
×
NEW
101
        if len(instruction.Args) > 0 {
×
NEW
102
                // For LOG0, no additional argument is needed
×
NEW
103
                if instruction.OpCode == LOG0 {
×
NEW
104
                        return []byte{}, nil
×
NEW
105
                }
×
106

107
                // For other LOG operations, extract event arguments
NEW
108
                eventArgs := instruction.Args[32:] // Skip the first 32 bytes (topic)
×
NEW
109
                return eventArgs, nil
×
110
        }
NEW
111
        return nil, nil
×
112
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc