Skip to content

Commit

Permalink
EVM parsing functions with ABI
Browse files Browse the repository at this point in the history
  • Loading branch information
pro-wh committed Jun 29, 2023
1 parent 2988d81 commit c5d8918
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
40 changes: 40 additions & 0 deletions api/logic/evm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package logic

import (
"fmt"

"github.com/ethereum/go-ethereum/accounts/abi"
ethCommon "github.com/ethereum/go-ethereum/common"
)

func EVMParseData(data []byte, contractABI *abi.ABI) (*abi.Method, []interface{}, error) {
if len(data) < 4 {
return nil, nil, fmt.Errorf("data (%dB) too short to have method ID", len(data))
}
methodID := data[:4]
packedArgs := data[4:]
method, err := contractABI.MethodById(methodID)
if err != nil {
return nil, nil, fmt.Errorf("contract ABI MethodById: %w", err)
}
args, err := method.Inputs.Unpack(packedArgs)
if err != nil {
return nil, nil, fmt.Errorf("method inputs Unpack: %w", err)
}
return method, args, nil
}

func EVMParseEvent(topics [][]byte, data []byte, contractABI *abi.ABI) (*abi.Event, []interface{}, error) {
if len(topics) < 1 {
return nil, nil, fmt.Errorf("topics (%d) too short to have event signature", len(topics))
}
event, err := contractABI.EventByID(ethCommon.BytesToHash(topics[0]))
if err != nil {
return nil, nil, fmt.Errorf("contract ABI EventByID: %w", err)
}
args, err := event.Inputs.Unpack(data)
if err != nil {
return nil, nil, fmt.Errorf("event inputs Unpack: %w", err)
}
return event, args, nil
}
47 changes: 47 additions & 0 deletions api/logic/evm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package logic

import (
"encoding/hex"
"math/big"
"testing"

ethCommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"github.com/oasisprotocol/nexus/analyzer/evmabi"
)

func TestEVMParseData(t *testing.T) {
// https://explorer.emerald.oasis.dev/tx/0x1ac7521df4cda38c87cff56b1311ee9362168bd794230415a37f2aff3a554a5f/internal-transactions
data, err := hex.DecodeString("095ea7b3000000000000000000000000250d48c5e78f1e85f7ab07fec61e93ba703ae6680000000000000000000000000000000000000000000000003782dace9d900000")
require.NoError(t, err)
method, args, err := EVMParseData(data, evmabi.ERC20)
require.NoError(t, err)
require.Equal(t, evmabi.ERC20.Methods["approve"], *method)
require.Equal(t, []interface{}{
ethCommon.HexToAddress("0x250d48c5e78f1e85f7ab07fec61e93ba703ae668"),
big.NewInt(4000000000000000000),
}, args)
}

func TestEVMParseEvent(t *testing.T) {
// https://explorer.emerald.oasis.dev/tx/0x1ac7521df4cda38c87cff56b1311ee9362168bd794230415a37f2aff3a554a5f/logs
topicsHex := []string{
"8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925",
"0000000000000000000000000ecf5262e5b864e1612875f8fc18f151315b5e91",
"000000000000000000000000250d48c5e78f1e85f7ab07fec61e93ba703ae668",
}
var topics [][]byte
for _, topicHex := range topicsHex {
topic, err := hex.DecodeString(topicHex)
require.NoError(t, err)
topics = append(topics, topic)
}
data, err := hex.DecodeString("0000000000000000000000000000000000000000000000003782dace9d900000")
require.NoError(t, err)
event, args, err := EVMParseEvent(topics, data, evmabi.ERC20)
require.Equal(t, evmabi.ERC20.Events["Approval"], *event)
require.Equal(t, []interface{}{
big.NewInt(4000000000000000000),
}, args)
}

0 comments on commit c5d8918

Please sign in to comment.