From 3d750f318cd6a4203677bcc3ce279b63ad1b03fd Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Thu, 26 Sep 2024 13:12:58 -0400 Subject: [PATCH 1/2] intents: use ethcoder abi parser for more robust abi string parsing --- .../intent_data_transaction_delayed_abi.go | 58 +++++-------------- ...ntent_data_transaction_delayed_abi_test.go | 4 +- 2 files changed, 16 insertions(+), 46 deletions(-) diff --git a/intents/intent_data_transaction_delayed_abi.go b/intents/intent_data_transaction_delayed_abi.go index 4c046452..b8416f4c 100644 --- a/intents/intent_data_transaction_delayed_abi.go +++ b/intents/intent_data_transaction_delayed_abi.go @@ -116,55 +116,25 @@ func getMethodFromAbi(abi string, method string) (string, []string, error) { } `json:"inputs"` } + // + // 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) { - // 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 + eventDef, err := ethcoder.ParseEventDef(abi) + if err != nil { + return "", nil, err } - - // Re encode abi, now without name information - fnc := method + "(" + strings.Join(types, ",") + ")" - return fnc, order, nil + 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 + // + // 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 da1315b6..12d5ff4f 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) { From 3a357f9503141373c6d48ec477b6d028ac970bee Mon Sep 17 00:00:00 2001 From: Peter Kieltyka Date: Thu, 26 Sep 2024 13:15:08 -0400 Subject: [PATCH 2/2] comment --- .../intent_data_transaction_delayed_abi.go | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/intents/intent_data_transaction_delayed_abi.go b/intents/intent_data_transaction_delayed_abi.go index b8416f4c..d53f709d 100644 --- a/intents/intent_data_transaction_delayed_abi.go +++ b/intents/intent_data_transaction_delayed_abi.go @@ -106,16 +106,6 @@ 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) { - type FunctionAbi struct { - Name string `json:"name"` - Type string `json:"type"` - Inputs []struct { - InternalType string `json:"internalType"` - Name string `json:"name"` - Type string `json:"type"` - } `json:"inputs"` - } - // // First attempt to parse `abi` string as a plain method abi // ie. transferFrom(address,address,uint256) @@ -123,6 +113,9 @@ func getMethodFromAbi(abi string, method string) (string, []string, error) { // 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 @@ -135,6 +128,16 @@ func getMethodFromAbi(abi string, method string) (string, []string, error) { // a JSON object of the full abi definition // + type FunctionAbi struct { + Name string `json:"name"` + Type string `json:"type"` + Inputs []struct { + InternalType string `json:"internalType"` + Name string `json:"name"` + Type string `json:"type"` + } `json:"inputs"` + } + // Handle array of function abis and single function abi var abis []FunctionAbi if strings.HasPrefix(abi, "[") {