Skip to content

Commit

Permalink
feat: add methods signature parser, decouple ABI parser
Browse files Browse the repository at this point in the history
  • Loading branch information
kamikazechaser committed Mar 25, 2024
1 parent bf867f4 commit d8b99a9
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 61 deletions.
49 changes: 49 additions & 0 deletions abi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package celoutils

import (
"io"

"github.com/celo-org/celo-blockchain/accounts/abi"
)

type (
ParsedABI struct {
EventSignatures []EventSignature
MethodSignatures []MethodSignature
}
)

func ParseABI(abiReader io.Reader) (*ParsedABI, error) {
abi, err := abi.JSON(abiReader)
if err != nil {
return nil, err
}

var (
eventSignatures []EventSignature
methodsSignatures []MethodSignature
)

for _, v := range abi.Events {
eventSignature, err := EventSignatureFromString(v.Sig)
if err != nil {
return nil, err
}

eventSignatures = append(eventSignatures, eventSignature)
}

for _, v := range abi.Methods {
methodSignature, err := MethodSignatureFromString(v.Sig)
if err != nil {
return nil, err
}

methodsSignatures = append(methodsSignatures, methodSignature)
}

return &ParsedABI{
EventSignatures: eventSignatures,
MethodSignatures: methodsSignatures,
}, nil
}
57 changes: 57 additions & 0 deletions abi_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package celoutils

import (
"reflect"
"strings"
"testing"
)

func TestParseABI(t *testing.T) {
// contract T {
// event received(address sender, uint amount, bytes memo);
// event receivedAddr(address sender);
// function receive(bytes memo) external payable {
// received(msg.sender, msg.value, memo);
// receivedAddr(msg.sender);
// }
// }
// https://www.4byte.directory/event-signatures
// 253837 received(address,uint256,bytes) 0x75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed
// 253838 receivedAddr(address) 0x46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c8
eventSignatures := []EventSignature{
{
Signature: "received(address,uint256,bytes)",
Hash: "0x75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed",
},
{
Signature: "receivedAddr(address)",
Hash: "0x46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c8",
},
}

methodSignatures := []MethodSignature{
{
Signature: "receive(bytes)",
Hash: "a69b6ed0",
},
}

want := &ParsedABI{
EventSignatures: eventSignatures,
MethodSignatures: methodSignatures,
}

json := `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
got, err := ParseABI(strings.NewReader(json))
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(got.EventSignatures, want.EventSignatures) {
t.Errorf("Event signatures slices should be equal, got %v and %v", got, want)
}

if !reflect.DeepEqual(got.MethodSignatures, want.MethodSignatures) {
t.Errorf("Method signatures slices should be equal, got %v and %v", got, want)
}
}
24 changes: 1 addition & 23 deletions event.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package celoutils

import (
"io"
"strings"

"github.com/celo-org/celo-blockchain/accounts/abi"
"github.com/grassrootseconomics/w3-celo"
)

Expand All @@ -15,7 +13,7 @@ type (
}
)

func EventSignatureHash(eventSignature string) (EventSignature, error) {
func EventSignatureFromString(eventSignature string) (EventSignature, error) {
event, err := w3.NewEvent(strings.TrimSuffix(eventSignature, ";"))
if err != nil {
return EventSignature{}, err
Expand All @@ -26,23 +24,3 @@ func EventSignatureHash(eventSignature string) (EventSignature, error) {
Hash: event.Topic0.Hex(),
}, nil
}

func EventSignatureHashesFromABI(abiReader io.Reader) ([]EventSignature, error) {
abi, err := abi.JSON(abiReader)
if err != nil {
return nil, err
}

var eventSignatures []EventSignature

for _, v := range abi.Events {
eventSignatureHash, err := EventSignatureHash(v.Sig)
if err != nil {
return nil, err
}

eventSignatures = append(eventSignatures, eventSignatureHash)
}

return eventSignatures, nil
}
40 changes: 2 additions & 38 deletions event_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package celoutils

import (
"reflect"
"strings"
"testing"
)

Expand Down Expand Up @@ -38,7 +36,7 @@ func TestEventSignatureHash(t *testing.T) {
{
name: "Transfer Event variant 3",
args: args{
event: "Transfer(address indexed _from, address indexed _to, uint256 _value)",
event: "Transfer(address indexed _from, address indexed _to, uint256 _value);",
},
want: EventSignature{
Signature: "Transfer(address,address,uint256)",
Expand All @@ -48,7 +46,7 @@ func TestEventSignatureHash(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := EventSignatureHash(tt.args.event)
got, err := EventSignatureFromString(tt.args.event)
if err != nil {
t.Errorf("EventSignatureHash() got error: %v", err)
}
Expand All @@ -58,37 +56,3 @@ func TestEventSignatureHash(t *testing.T) {
})
}
}

func TestEventSignatureHashesFromABI(t *testing.T) {
// contract T {
// event received(address sender, uint amount, bytes memo);
// event receivedAddr(address sender);
// function receive(bytes memo) external payable {
// received(msg.sender, msg.value, memo);
// receivedAddr(msg.sender);
// }
// }
// https://www.4byte.directory/event-signatures
// 253837 received(address,uint256,bytes) 0x75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed
// 253838 receivedAddr(address) 0x46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c8
want := []EventSignature{
{
Signature: "received(address,uint256,bytes)",
Hash: "0x75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed",
},
{
Signature: "receivedAddr(address)",
Hash: "0x46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c8",
},
}

json := `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
got, err := EventSignatureHashesFromABI(strings.NewReader(json))
if err != nil {
t.Fatal(err)
}

if !reflect.DeepEqual(got, want) {
t.Errorf("Slices should be equal, got %v and %v", got, want)
}
}
26 changes: 26 additions & 0 deletions method.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package celoutils

import (
"encoding/hex"

"github.com/grassrootseconomics/w3-celo"
)

type (
MethodSignature struct {
Signature string
Hash string
}
)

func MethodSignatureFromString(methodSignature string) (MethodSignature, error) {
method, err := w3.NewFunc(methodSignature, "")
if err != nil {
return MethodSignature{}, err
}

return MethodSignature{
Signature: method.Signature,
Hash: hex.EncodeToString(method.Selector[:]),
}, nil
}
41 changes: 41 additions & 0 deletions method_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package celoutils

import (
"reflect"
"testing"
)

func TestMethodSignatureFromString(t *testing.T) {
type args struct {
methodSignature string
}
tests := []struct {
name string
args args
want MethodSignature
wantErr bool
}{
{
name: "Transfer Method",
args: args{
methodSignature: "transfer(address, uint256)",
},
want: MethodSignature{
Signature: "transfer(address,uint256)",
Hash: "a9059cbb",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := MethodSignatureFromString(tt.args.methodSignature)
if (err != nil) != tt.wantErr {
t.Errorf("MethodSignatureFromString() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("MethodSignatureFromString() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit d8b99a9

Please sign in to comment.