Skip to content

Commit 2f16f10

Browse files
authored
ABI: Bugfix - now it's compliant (#165)
* Abi updates * Fixing unit tests * Overall data tests
1 parent 6089f2f commit 2f16f10

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+943
-6279
lines changed

abi/builder.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ func NewBuilderFromSources(ctx context.Context, sources *solgo.Sources) (*Builde
3636
parser: parser,
3737
astBuilder: parser.GetAstBuilder(),
3838
resolver: &TypeResolver{
39-
parser: parser,
39+
parser: parser,
40+
processedTypes: make(map[string]bool),
4041
},
4142
}, nil
4243
}
@@ -124,9 +125,11 @@ func (b *Builder) Parse() (errs []error) {
124125
}
125126

126127
// Build constructs the ABIs from the sources.
127-
func (b *Builder) Build() error {
128+
func (b *Builder) Build() (err error) {
128129
if root := b.GetParser().GetRoot(); root != nil {
129-
b.root = b.processRoot(root)
130+
if b.root, err = b.processRoot(root); err != nil {
131+
return err
132+
}
130133
}
131134
return nil
132135
}

abi/constructor.go

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package abi
22

3-
import "github.com/unpackdev/solgo/ir"
3+
import (
4+
"fmt"
5+
6+
"github.com/unpackdev/solgo/ir"
7+
)
48

59
// processConstructor processes an IR constructor and returns a Method representation of it.
610
// It extracts the input and output parameters of the constructor and normalizes its state mutability.
7-
func (b *Builder) processConstructor(unit *ir.Constructor) *Method {
11+
func (b *Builder) processConstructor(unit *ir.Constructor) (*Method, error) {
812
// Initialize a new Method structure for the constructor.
913
toReturn := &Method{
1014
Name: "", // Constructors in Ethereum don't have a name.
@@ -15,6 +19,10 @@ func (b *Builder) processConstructor(unit *ir.Constructor) *Method {
1519
}
1620

1721
for _, parameter := range unit.GetParameters() {
22+
if parameter.GetTypeDescription() == nil {
23+
return nil, fmt.Errorf("nil type description for constructor parameter %s", parameter.GetName())
24+
}
25+
1826
methodIo := MethodIO{
1927
Name: parameter.GetName(),
2028
}
@@ -24,17 +32,5 @@ func (b *Builder) processConstructor(unit *ir.Constructor) *Method {
2432
)
2533
}
2634

27-
// Process return statements of the constructor.
28-
// Note: In Ethereum, constructors don't return values. This might be specific to the IR representation.
29-
/* for _, parameter := range unit.GetReturnStatements() {
30-
methodIo := MethodIO{
31-
Name: parameter.GetName(),
32-
}
33-
toReturn.Outputs = append(
34-
toReturn.Outputs,
35-
b.buildMethodIO(methodIo, parameter.GetTypeDescription()),
36-
)
37-
} */
38-
39-
return toReturn
35+
return toReturn, nil
4036
}

abi/constructor_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ func TestProcessConstructor(t *testing.T) {
4747
}
4848

4949
builder := &Builder{}
50-
result := builder.processConstructor(mockConstructor)
50+
result, err := builder.processConstructor(mockConstructor)
51+
assert.NoError(t, err)
5152

5253
// Assert that the returned Method object has the expected properties
5354
assert.Equal(t, "constructor", result.Type)

abi/contract.go

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package abi
22

33
import (
44
abi_pb "github.com/unpackdev/protos/dist/go/abi"
5+
ast_pb "github.com/unpackdev/protos/dist/go/ast"
56
"github.com/unpackdev/solgo/ast"
67
"github.com/unpackdev/solgo/ir"
78
)
@@ -44,7 +45,7 @@ func (c *Contract) ToProto() *abi_pb.Contract {
4445

4546
// processContract processes an IR contract and returns a Contract representation of it.
4647
// It extracts state variables, events, errors, constructor, functions, fallback, and receive methods.
47-
func (b *Builder) processContract(contract *ir.Contract) *Contract {
48+
func (b *Builder) processContract(contract *ir.Contract) (*Contract, error) {
4849
toReturn := Contract{}
4950

5051
// Process state variables.
@@ -55,28 +56,44 @@ func (b *Builder) processContract(contract *ir.Contract) *Contract {
5556

5657
// Process events.
5758
for _, event := range contract.GetEvents() {
58-
method := b.processEvent(event)
59+
method, err := b.processEvent(event)
60+
if err != nil {
61+
return nil, err
62+
}
63+
5964
toReturn = append(toReturn, method)
6065
}
6166

6267
// Process errors.
6368
for _, errorNode := range contract.GetErrors() {
64-
method := b.processError(errorNode)
69+
method, err := b.processError(errorNode)
70+
if err != nil {
71+
return nil, err
72+
}
73+
6574
toReturn = append(toReturn, method)
6675
}
6776

6877
// Process constructor.
6978
if contract.GetConstructor() != nil {
70-
toReturn = append(
71-
toReturn,
72-
b.processConstructor(contract.GetConstructor()),
73-
)
79+
method, err := b.processConstructor(contract.GetConstructor())
80+
if err != nil {
81+
return nil, err
82+
}
83+
84+
toReturn = append(toReturn, method)
7485
}
7586

7687
// Process functions.
7788
for _, function := range contract.GetFunctions() {
78-
method := b.processFunction(function)
79-
toReturn = append(toReturn, method)
89+
if function.GetVisibility() == ast_pb.Visibility_PUBLIC && function.GetVisibility() == ast_pb.Visibility_EXTERNAL {
90+
method, err := b.processFunction(function)
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
toReturn = append(toReturn, method)
96+
}
8097
}
8198

8299
// Process fallback.
@@ -89,13 +106,15 @@ func (b *Builder) processContract(contract *ir.Contract) *Contract {
89106

90107
// Process receive.
91108
if contract.GetReceive() != nil {
92-
toReturn = append(
93-
toReturn,
94-
b.processReceive(contract.GetReceive()),
95-
)
109+
method, err := b.processReceive(contract.GetReceive())
110+
if err != nil {
111+
return nil, err
112+
}
113+
114+
toReturn = append(toReturn, method)
96115
}
97116

98-
return &toReturn
117+
return &toReturn, nil
99118
}
100119

101120
// buildMethodIO constructs a MethodIO object based on the provided method and type description.

abi/error.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package abi
22

33
import (
4+
"fmt"
5+
46
"github.com/unpackdev/solgo/ir"
57
)
68

79
// processError processes an IR error and returns a Method representation of it.
810
// It extracts the name and parameters of the error and sets its type to "error" and state mutability to "view".
9-
func (b *Builder) processError(unit *ir.Error) *Method {
11+
func (b *Builder) processError(unit *ir.Error) (*Method, error) {
1012
toReturn := &Method{
1113
Name: unit.GetName(),
1214
Inputs: make([]MethodIO, 0),
@@ -16,13 +18,19 @@ func (b *Builder) processError(unit *ir.Error) *Method {
1618
}
1719

1820
for _, parameter := range unit.GetParameters() {
19-
toReturn.Inputs = append(toReturn.Inputs, MethodIO{
20-
Name: parameter.GetName(),
21-
Type: normalizeTypeName(parameter.GetTypeDescription().GetString()),
22-
InternalType: parameter.GetTypeDescription().GetString(),
23-
Indexed: true, // Parameters for errors are indexed by default.
24-
})
21+
if parameter.GetTypeDescription() == nil {
22+
return nil, fmt.Errorf("nil type description for error parameter %s", parameter.GetName())
23+
}
24+
25+
methodIo := MethodIO{
26+
Name: parameter.GetName(),
27+
Indexed: parameter.IsIndexed(),
28+
}
29+
toReturn.Inputs = append(
30+
toReturn.Inputs,
31+
b.buildMethodIO(methodIo, parameter.GetTypeDescription()),
32+
)
2533
}
2634

27-
return toReturn
35+
return toReturn, nil
2836
}

abi/error_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestProcessError(t *testing.T) {
3636
Name: "param1",
3737
Type: "uint256",
3838
InternalType: "uint256",
39-
Indexed: true,
39+
Indexed: false,
4040
},
4141
},
4242
Outputs: []MethodIO{},
@@ -52,12 +52,14 @@ func TestProcessError(t *testing.T) {
5252
TypeDescription: &ast.TypeDescription{
5353
TypeString: "uint256",
5454
},
55+
Indexed: true,
5556
},
5657
{
5758
Name: "param2",
5859
TypeDescription: &ast.TypeDescription{
5960
TypeString: "address",
6061
},
62+
Indexed: true,
6163
},
6264
},
6365
},
@@ -88,7 +90,8 @@ func TestProcessError(t *testing.T) {
8890

8991
for _, tt := range tests {
9092
t.Run(tt.name, func(t *testing.T) {
91-
result := builder.processError(tt.input)
93+
result, err := builder.processError(tt.input)
94+
assert.NoError(t, err)
9295
assert.Equal(t, tt.expected, result)
9396
})
9497
}

abi/event.go

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package abi
22

33
import (
4+
"fmt"
5+
46
"github.com/unpackdev/solgo/ir"
57
)
68

79
// processEvent processes an IR event and returns a Method representation of it.
810
// It extracts the name and parameters of the event and sets its type to "event" and state mutability to "view".
9-
func (b *Builder) processEvent(unit *ir.Event) *Method {
11+
func (b *Builder) processEvent(unit *ir.Event) (*Method, error) {
1012
toReturn := &Method{
1113
Name: unit.GetName(),
1214
Inputs: make([]MethodIO, 0),
@@ -16,15 +18,30 @@ func (b *Builder) processEvent(unit *ir.Event) *Method {
1618
}
1719

1820
// Process parameters of the event.
19-
// Note: In Ethereum, event parameters are considered as outputs.
21+
// Note: In Ethereum, event parameters are considered as inputs.
2022
for _, parameter := range unit.GetParameters() {
21-
toReturn.Outputs = append(toReturn.Outputs, MethodIO{
22-
Name: parameter.GetName(),
23-
Type: parameter.GetTypeDescription().TypeString,
24-
InternalType: parameter.GetTypeDescription().TypeString,
25-
Indexed: true, // Parameters for events can be indexed.
26-
})
23+
if parameter.GetTypeDescription() == nil {
24+
return nil, fmt.Errorf("nil type description for event parameter %s", parameter.GetName())
25+
}
26+
27+
methodIo := MethodIO{
28+
Name: parameter.GetName(),
29+
Indexed: parameter.IsIndexed(),
30+
}
31+
toReturn.Inputs = append(
32+
toReturn.Inputs,
33+
b.buildMethodIO(methodIo, parameter.GetTypeDescription()),
34+
)
35+
}
36+
37+
return toReturn, nil
38+
}
39+
40+
func (b *Builder) GetEventAsAbi(unit *ir.Event) ([]*Method, error) {
41+
method, err := b.processEvent(unit)
42+
if err != nil {
43+
return nil, err
2744
}
2845

29-
return toReturn
46+
return []*Method{method}, nil
3047
}

abi/event_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import (
99
)
1010

1111
func TestProcessEvent(t *testing.T) {
12-
builder := &Builder{}
12+
builder := &Builder{
13+
resolver: &TypeResolver{
14+
parser: nil,
15+
processedTypes: make(map[string]bool),
16+
},
17+
}
1318

1419
testCases := []struct {
1520
name string
@@ -29,6 +34,7 @@ func TestProcessEvent(t *testing.T) {
2934
TypeString: "uint256",
3035
TypeIdentifier: "t_uint256",
3136
},
37+
Indexed: true,
3238
},
3339
},
3440
},
@@ -40,10 +46,11 @@ func TestProcessEvent(t *testing.T) {
4046

4147
for _, tc := range testCases {
4248
t.Run(tc.name, func(t *testing.T) {
43-
result := builder.processEvent(tc.input)
49+
result, err := builder.processEvent(tc.input)
50+
assert.NoError(t, err)
4451
assert.Equal(t, tc.expectedType, result.Type)
4552
assert.Equal(t, tc.expectedName, result.Name)
46-
assert.Equal(t, tc.expectedOutputs, len(result.Outputs))
53+
assert.Equal(t, tc.expectedOutputs, len(result.Inputs))
4754
for _, output := range result.Outputs {
4855
assert.True(t, output.Indexed)
4956
}

abi/fallback.go

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Package abi provides tools for building and parsing Ethereum ABI (Application Binary Interface) data.
22
package abi
33

4-
import "github.com/unpackdev/solgo/ir"
4+
import (
5+
"github.com/unpackdev/solgo/ir"
6+
)
57

68
// processFallback processes an IR fallback function and returns a Method representation of it.
79
// It extracts the input and output parameters of the fallback function and normalizes its state mutability.
@@ -14,27 +16,5 @@ func (b *Builder) processFallback(unit *ir.Fallback) *Method {
1416
StateMutability: b.normalizeStateMutability(unit.GetStateMutability()),
1517
}
1618

17-
for _, parameter := range unit.GetParameters() {
18-
methodIo := MethodIO{
19-
Name: parameter.GetName(),
20-
}
21-
toReturn.Inputs = append(
22-
toReturn.Inputs,
23-
b.buildMethodIO(methodIo, parameter.GetTypeDescription()),
24-
)
25-
}
26-
27-
// Process return statements of the fallback function.
28-
// Note: In Ethereum, fallback functions can have return values.
29-
/* for _, parameter := range unit.GetReturnStatements() {
30-
methodIo := MethodIO{
31-
Name: parameter.GetName(),
32-
}
33-
toReturn.Outputs = append(
34-
toReturn.Outputs,
35-
b.buildMethodIO(methodIo, parameter.GetTypeDescription()),
36-
)
37-
} */
38-
3919
return toReturn
4020
}

abi/fallback_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ func TestProcessFallback(t *testing.T) {
5353
assert.Equal(t, "fallback", result.Type)
5454
assert.Equal(t, builder.normalizeStateMutability(mockFallback.GetStateMutability()), result.StateMutability)
5555
assert.Equal(t, "", result.Name)
56-
assert.Equal(t, 2, len(result.Inputs))
57-
assert.Equal(t, "inputParam1", result.Inputs[0].Name)
58-
assert.Equal(t, "inputParam2", result.Inputs[1].Name)
59-
assert.Equal(t, "uint256", result.Inputs[0].Type)
60-
assert.Equal(t, "uint256", result.Inputs[1].Type)
61-
assert.Equal(t, "uint256", result.Inputs[0].InternalType)
62-
assert.Equal(t, "uint256", result.Inputs[1].InternalType)
56+
assert.Equal(t, 0, len(result.Inputs))
6357
assert.Equal(t, 0, len(result.Outputs))
6458
}

0 commit comments

Comments
 (0)