From cc002ab2776923361677ecd80e93f4e5d14f589a Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Thu, 26 Sep 2024 13:33:17 -0400 Subject: [PATCH] intents: use ethcoder abi parser for more robust abi string parsing (#155) * intents: use ethcoder abi parser for more robust abi string parsing * comment --- .../intent_data_transaction_delayed_abi.go | 71 ++++++------------- ...ntent_data_transaction_delayed_abi_test.go | 4 +- 2 files changed, 24 insertions(+), 51 deletions(-) diff --git a/intents/intent_data_transaction_delayed_abi.go b/intents/intent_data_transaction_delayed_abi.go index 4c04645..d53f709 100644 --- a/intents/intent_data_transaction_delayed_abi.go +++ b/intents/intent_data_transaction_delayed_abi.go @@ -106,6 +106,28 @@ func EncodeDelayedABI(data *delayedEncodeType) (string, error) { // - transferFrom(address,address,uint256) // making sure that the method matches the returned one func getMethodFromAbi(abi string, method string) (string, []string, error) { + // + // First attempt to parse `abi` string as a plain method abi + // ie. transferFrom(address,address,uint256) + // + + // Handle the case for already encoded method abi + if strings.Contains(abi, "(") && strings.Contains(abi, ")") && strings.HasPrefix(abi, method) { + // NOTE: even though the ethcoder function is `ParseEventDef`, designed for event type parsing + // the abi format for a single function structure is the same, so it works. Perhaps we will rename + // `ParseEventDef` in the future, or just add another method with a different name. + eventDef, err := ethcoder.ParseEventDef(abi) + if err != nil { + return "", nil, err + } + return eventDef.Sig, eventDef.ArgNames, nil + } + + // + // If above didn't work, attempt to parse `abi` string as + // a JSON object of the full abi definition + // + type FunctionAbi struct { Name string `json:"name"` Type string `json:"type"` @@ -116,55 +138,6 @@ func getMethodFromAbi(abi string, method string) (string, []string, error) { } `json:"inputs"` } - // Handle the case for already encoded method abi - if strings.Contains(abi, "(") && strings.Contains(abi, ")") && strings.HasPrefix(abi, method) { - // We may or may not have name information - // transferFrom(address,address,uint256) - // vs - // transferFrom(address from,address to,uint256 val) - - // Start by obtaning only the args - args := strings.Split(abi, "(")[1] - args = strings.Split(args, ")")[0] - - // Split the args by comma, to get the individual types - argTypes := strings.Split(args, ",") - - order := make([]string, len(argTypes)) - types := make([]string, len(argTypes)) - - incompleteNaming := false - - for i, arg := range argTypes { - // If starts with space, trim it - arg = strings.TrimLeft(arg, " ") - - if strings.Contains(arg, " ") { - // We have name information, so we need to extract it - spl := strings.Split(arg, " ") - - order[i] = spl[1] - types[i] = spl[0] - - } else { - // We don't have name information, so we must - // mark this case as incomplete - incompleteNaming = true - - // Assume that arg is the type - types[i] = arg - } - } - - if incompleteNaming { - order = nil - } - - // Re encode abi, now without name information - fnc := method + "(" + strings.Join(types, ",") + ")" - return fnc, order, nil - } - // Handle array of function abis and single function abi var abis []FunctionAbi if strings.HasPrefix(abi, "[") { diff --git a/intents/intent_data_transaction_delayed_abi_test.go b/intents/intent_data_transaction_delayed_abi_test.go index da1315b..12d5ff4 100644 --- a/intents/intent_data_transaction_delayed_abi_test.go +++ b/intents/intent_data_transaction_delayed_abi_test.go @@ -46,7 +46,7 @@ func TestGetMethodFromABI(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "transfer(address,uint256)", res) - assert.Nil(t, order) + assert.Equal(t, []string{"arg1", "arg2"}, order) // From plain method, with named args res, order, err = getMethodFromAbi(`transfer(address _to,uint256 _value, bytes _mas)`, "transfer") @@ -60,7 +60,7 @@ func TestGetMethodFromABI(t *testing.T) { assert.Nil(t, err) assert.Equal(t, "transfer(address,uint256,bytes)", res) - assert.Nil(t, order) + assert.Equal(t, []string{"_to", "arg2", "_mas"}, order) } func TestEncodeDelayedABI(t *testing.T) {