umbracle / ethgo

Ethereum Golang API
https://www.ethgoproject.io
Mozilla Public License 2.0
484 stars 134 forks source link

encode nested tuple error #236

Closed 0xfaceDEFI closed 1 year ago

0xfaceDEFI commented 1 year ago

code

import (
    "fmt"
    "github.com/umbracle/ethgo"
    "github.com/umbracle/ethgo/abi"
    "github.com/umbracle/ethgo/contract"
    "github.com/umbracle/ethgo/jsonrpc"
    "github.com/umbracle/ethgo/wallet"
    "math/big"
    "testing"
)

type SwapParams struct {
    PoolID    [32]byte
    Kind      *big.Int
    AssertIn  string
    AssertOut string
    Amount    *big.Int
    UserData  []byte
}

type FunderParams struct {
    Sender              string
    FromInternalBalance bool
    Recipient           string
    ToInternalBalance   bool
}

func MethodEncode(function string, args ...interface{}) ([]byte, error) {
    method, err := abi.NewMethod(function)
    if err != nil {
        return nil, err
    }
    data, err := method.Encode(args)
    if err != nil {
        return nil, err
    }
    return data, nil
}

func TestEncodeNestedTuple(t *testing.T) {
    poolID := [32]byte{}
    copy(poolID[:], "0xf3946a0e5368f716b1f40586272c9066b419035c000200000000000000000424")
    swapParams := SwapParams{
        PoolID:    poolID,
        Kind:      big.NewInt(0),
        AssertIn:  "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        AssertOut: "0xfd0205066521550D7d7AB19DA8F72bb004b4C341",
        Amount:    big.NewInt(500000000),
        UserData:  []byte("0x"),
    }
    funderParams := FunderParams{
        Sender:              "0x8EbEC7277a5c0C43ac708BC641CBF9756E7938f4",
        FromInternalBalance: false,
        Recipient:           "0x8EbEC7277a5c0C43ac708BC641CBF9756E7938f4",
        ToInternalBalance:   false,
    }

    encodeData, err := MethodEncode("swap((bytes32,uint8,address,address,uint256,bytes),(address,bool,address,bool),uint256,uint256)", swapParams, funderParams, 1, 1)
    if err != nil {
        panic(err)
    }
    fmt.Println(encodeData)
}

result

--- FAIL: TestEncodeNestedTuple (0.00s)
panic: cannot get key  [recovered]
    panic: cannot get key 
image
ferranbt commented 1 year ago

Apologize for the late response.

The error is that the abi encoder does not know how to match the inputs in the function signature with the struct. If it were a list instead, it matches by index (i.e. input at index 1 is item at index 1) but it needs a name when working with structs.

To fix it, you have to assign a name to the input and a tag to the fields in the struct:

type SwapParams struct {
    PoolID    [32]byte `abi:"a"`
    Kind      *big.Int `abi:"b"`
    AssertIn  string   `abi:"c"`
    AssertOut string   `abi:"d"`
    Amount    *big.Int `abi:"e"`
    UserData  []byte   `abi:"f"`
}

type FunderParams struct {
    Sender              string `abi:"a"`
    FromInternalBalance bool   `abi:"b"`
    Recipient           string `abi:"c"`
    ToInternalBalance   bool   `abi:"d"`
}

...

encodeData, err := MethodEncode("swap((bytes32 a,uint8 b,address c,address d,uint256 e,bytes f),(address a,bool b,address c,bool d),uint256,uint256)", swapParams, funderParams, 1, 1)
if err != nil {
    panic(err)
}