github.com/0xsequence/ethkit@v1.25.0/ethcoder/abi_test.go (about)

     1  package ethcoder
     2  
     3  import (
     4  	"math/big"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/0xsequence/ethkit/go-ethereum/common"
     9  	"github.com/0xsequence/ethkit/go-ethereum/common/hexutil"
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestAbiEncoding(t *testing.T) {
    14  	cases := []struct {
    15  		argTypes []string
    16  		expected string
    17  		input    []interface{}
    18  	}{
    19  		{
    20  			argTypes: []string{
    21  				"uint256[]",
    22  				"uint256[]",
    23  			},
    24  			expected: `0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000016`,
    25  			input: []interface{}{
    26  				[]*big.Int{big.NewInt(44)},
    27  				[]*big.Int{big.NewInt(22)},
    28  			},
    29  		},
    30  	}
    31  
    32  	for _, i := range cases {
    33  		packed, err := AbiCoder(i.argTypes, i.input)
    34  		assert.NoError(t, err)
    35  
    36  		// the expected value is the same
    37  		assert.Equal(t, i.expected, hexutil.Encode(packed))
    38  
    39  		// decode the value
    40  		output := make([]interface{}, len(i.argTypes))
    41  		err = AbiDecoder(i.argTypes, packed, output)
    42  		assert.NoError(t, err)
    43  
    44  		if !reflect.DeepEqual(output, i.input) {
    45  			t.Fatal("encode/decode do not match")
    46  		}
    47  	}
    48  }
    49  
    50  func TestAbiDecoder(t *testing.T) {
    51  	{
    52  		input, err := HexDecode("0x000000000000000000000000000000000000000000007998f984c2040a5a9e01000000000000000000000000000000000000000000007998f984c2040a5a9e01")
    53  		assert.NoError(t, err)
    54  		var num, num2 *big.Int
    55  		err = AbiDecoder([]string{"uint256", "uint256"}, input, []interface{}{&num, &num2})
    56  		assert.NoError(t, err)
    57  	}
    58  
    59  	{
    60  		input, err := HexDecode("0x000000000000000000000000000000000000000000007998f984c2040a5a9e01")
    61  		assert.NoError(t, err)
    62  		var num *big.Int
    63  		err = AbiDecoder([]string{"uint256"}, input, []interface{}{&num})
    64  		assert.NoError(t, err)
    65  	}
    66  
    67  	{
    68  		input, err := HexDecode("0x000000000000000000000000000000000000000000007998f984c2040a5a9e01")
    69  		assert.NoError(t, err)
    70  
    71  		values, err := AbiDecoderWithReturnedValues([]string{"uint256"}, input)
    72  		assert.NoError(t, err)
    73  		assert.Len(t, values, 1)
    74  
    75  		num, ok := values[0].(*big.Int)
    76  		assert.True(t, ok)
    77  		assert.Equal(t, "574228229235365901934081", num.String())
    78  	}
    79  }
    80  
    81  func TestParseMethodABI(t *testing.T) {
    82  	// correct usage
    83  	{
    84  		mabi, methodName, err := ParseMethodABI("balanceOf(address,uint256)", "uint256")
    85  		assert.NoError(t, err)
    86  		assert.Equal(t, "balanceOf", methodName)
    87  
    88  		ownerAddress := common.HexToAddress("0x6615e4e985bf0d137196897dfa182dbd7127f54f")
    89  		data, err := mabi.Pack("balanceOf", ownerAddress, big.NewInt(2))
    90  		assert.NoError(t, err)
    91  
    92  		assert.Equal(t, "0x00fdd58e0000000000000000000000006615e4e985bf0d137196897dfa182dbd7127f54f0000000000000000000000000000000000000000000000000000000000000002", HexEncode(data))
    93  	}
    94  
    95  	// correct usage
    96  	{
    97  		_, _, err := ParseMethodABI("someMethod(address)", "(uint256, bytes)")
    98  		assert.NoError(t, err)
    99  
   100  		// we also allow names for input/output arguments
   101  		_, _, err = ParseMethodABI("someMethod(address owner)", "(uint256 count, bytes value)")
   102  		assert.NoError(t, err)
   103  
   104  		// no args
   105  		_, _, err = ParseMethodABI("read()", "uint256")
   106  		assert.NoError(t, err)
   107  	}
   108  
   109  	// invalid usage
   110  	{
   111  		_, _, err := ParseMethodABI("balanceOf address, uint256)", "uint256")
   112  		assert.Error(t, err)
   113  
   114  		_, _, err = ParseMethodABI("balanceOf(address, uint256)", "blah")
   115  		assert.Contains(t, "unsupported arg type: blah", err.Error())
   116  	}
   117  }
   118  
   119  func TestAbiEncodeMethodCalldata(t *testing.T) {
   120  	ownerAddress := common.HexToAddress("0x6615e4e985bf0d137196897dfa182dbd7127f54f")
   121  
   122  	{
   123  		calldata, err := AbiEncodeMethodCalldata("balanceOf(address,uint256)", []interface{}{ownerAddress, big.NewInt(2)})
   124  		assert.NoError(t, err)
   125  		assert.Equal(t, "0x00fdd58e0000000000000000000000006615e4e985bf0d137196897dfa182dbd7127f54f0000000000000000000000000000000000000000000000000000000000000002", HexEncode(calldata))
   126  
   127  		// arrays
   128  		calldata, err = AbiEncodeMethodCalldata("getCurrencyReserves(uint256[])", []interface{}{[]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}})
   129  		assert.NoError(t, err)
   130  		assert.Equal(t, "0x209b96c500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", HexEncode(calldata))
   131  	}
   132  
   133  	{
   134  		calldata, err := AbiEncodeMethodCalldataFromStringValues("balanceOf(address,uint256)", []string{"0x6615e4e985bf0d137196897dfa182dbd7127f54f", "2"})
   135  		assert.NoError(t, err)
   136  		assert.Equal(t, "0x00fdd58e0000000000000000000000006615e4e985bf0d137196897dfa182dbd7127f54f0000000000000000000000000000000000000000000000000000000000000002", HexEncode(calldata)) // same as above
   137  
   138  		// arrays
   139  		calldata, err = AbiEncodeMethodCalldataFromStringValues("getCurrencyReserves(uint256[])", []string{`["1","2","3"]`})
   140  		assert.NoError(t, err)
   141  		assert.Equal(t, "0x209b96c500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", HexEncode(calldata)) // same as above
   142  	}
   143  }
   144  
   145  func TestAbiDecodeExpr(t *testing.T) {
   146  	ret := "0x000000000000000000000000000000000000000000007998f984c2040a5a9e01"
   147  
   148  	{
   149  		retTrimmed, err := HexTrimLeadingZeros(ret)
   150  		assert.NoError(t, err)
   151  		assert.Equal(t, "0x7998f984c2040a5a9e01", retTrimmed)
   152  
   153  		val, err := hexutil.DecodeBig(retTrimmed)
   154  		assert.NoError(t, err)
   155  		assert.Equal(t, "574228229235365901934081", val.String())
   156  	}
   157  
   158  	{
   159  		input, err := HexDecode(ret)
   160  		assert.NoError(t, err)
   161  
   162  		var num *big.Int
   163  		output := []interface{}{&num}
   164  
   165  		err = AbiDecodeExpr("uint256", input, output)
   166  		assert.NoError(t, err)
   167  		assert.Equal(t, "574228229235365901934081", num.String())
   168  	}
   169  }
   170  
   171  func TestAbiDecodeExprAndStringify(t *testing.T) {
   172  	{
   173  		values, err := AbiDecodeExprAndStringify("uint256", MustHexDecode("0x000000000000000000000000000000000000000000007998f984c2040a5a9e01"))
   174  		assert.NoError(t, err)
   175  		assert.Len(t, values, 1)
   176  		assert.Equal(t, "574228229235365901934081", values[0])
   177  	}
   178  
   179  	{
   180  		data, err := AbiCoder([]string{"uint256", "address"}, []interface{}{big.NewInt(1337), common.HexToAddress("0x6615e4e985bf0d137196897dfa182dbd7127f54f")})
   181  		assert.NoError(t, err)
   182  
   183  		values, err := AbiDecodeExprAndStringify("(uint256,address)", data)
   184  		assert.NoError(t, err)
   185  		assert.Len(t, values, 2)
   186  		assert.Equal(t, "1337", values[0])
   187  		assert.Equal(t, "0x6615e4e985BF0D137196897Dfa182dBD7127f54f", values[1])
   188  	}
   189  
   190  	{
   191  		data, err := AbiCoder([]string{"bool", "bool"}, []interface{}{true, false})
   192  		assert.NoError(t, err)
   193  
   194  		values, err := AbiDecodeExprAndStringify("(bool,bool)", data)
   195  		assert.NoError(t, err)
   196  		assert.Len(t, values, 2)
   197  		assert.Equal(t, "true", values[0])
   198  		assert.Equal(t, "false", values[1])
   199  	}
   200  
   201  	{
   202  		data, err := AbiCoder([]string{"bytes"}, []interface{}{[]byte{1, 2, 3, 4}})
   203  		assert.NoError(t, err)
   204  
   205  		values, err := AbiDecodeExprAndStringify("(bytes)", data)
   206  		assert.NoError(t, err)
   207  		assert.Len(t, values, 1)
   208  		assert.Equal(t, "[1 2 3 4]", values[0])
   209  	}
   210  }
   211  
   212  func TestAbiUnmarshalStringValues(t *testing.T) {
   213  	{
   214  		values, err := AbiUnmarshalStringValues([]string{"address", "uint256"}, []string{"0x6615e4e985bf0d137196897dfa182dbd7127f54f", "2"})
   215  		assert.NoError(t, err)
   216  		assert.Len(t, values, 2)
   217  
   218  		v1, ok := values[0].(common.Address)
   219  		assert.True(t, ok)
   220  		assert.Equal(t, "0x6615e4e985BF0D137196897Dfa182dBD7127f54f", v1.String())
   221  
   222  		v2, ok := values[1].(*big.Int)
   223  		assert.True(t, ok)
   224  		assert.Equal(t, int64(2), v2.Int64())
   225  	}
   226  
   227  	{
   228  		values, err := AbiUnmarshalStringValues([]string{"address", "bytes8"}, []string{"0x6615e4e985bf0d137196897dfa182dbd7127f54f", "0xaabbccddaabbccdd"})
   229  		assert.NoError(t, err)
   230  
   231  		v1, ok := values[0].(common.Address)
   232  		assert.True(t, ok)
   233  		assert.Equal(t, "0x6615e4e985BF0D137196897Dfa182dBD7127f54f", v1.String())
   234  
   235  		v2, ok := values[1].([]uint8)
   236  		assert.True(t, ok)
   237  		assert.Equal(t, []uint8{170, 187, 204, 221, 170, 187, 204, 221}, v2)
   238  	}
   239  
   240  	{
   241  		values, err := AbiUnmarshalStringValues([]string{"address", "bytes7"}, []string{"0x6615e4e985bf0d137196897dfa182dbd7127f54f", "0xaabbccddaabbcc"})
   242  		assert.NoError(t, err)
   243  
   244  		v1, ok := values[0].(common.Address)
   245  		assert.True(t, ok)
   246  		assert.Equal(t, "0x6615e4e985BF0D137196897Dfa182dBD7127f54f", v1.String())
   247  
   248  		v2, ok := values[1].([]uint8)
   249  		assert.True(t, ok)
   250  		assert.Equal(t, []uint8{170, 187, 204, 221, 170, 187, 204}, v2)
   251  	}
   252  
   253  	{
   254  		values, err := AbiUnmarshalStringValues([]string{"address", "uint256"}, []string{"", "2"})
   255  		assert.Error(t, err)
   256  		assert.Len(t, values, 0)
   257  	}
   258  
   259  	{
   260  		values, err := AbiUnmarshalStringValues([]string{"bytes", "uint256"}, []string{"0", "2"})
   261  		assert.Error(t, err)
   262  		assert.Len(t, values, 0)
   263  	}
   264  
   265  	{
   266  		values, err := AbiUnmarshalStringValues([]string{"bytes", "uint256"}, []string{"0z", "2"})
   267  		assert.Error(t, err)
   268  		assert.Len(t, values, 0)
   269  	}
   270  }
   271  
   272  // func TestAbiContractCall1(t *testing.T) {
   273  // 	calldata, err := AbiEncodeMethodCalldata("getCurrencyReserves(uint256[])", []interface{}{[]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}})
   274  // 	assert.NoError(t, err)
   275  // 	assert.Equal(t, "0x209b96c500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", HexEncode(calldata))
   276  
   277  // 	ca := common.HexToAddress("0xa519711c25a631e55a6eac19d1f2858c97a86a95")
   278  // 	txMsg := ethereum.CallMsg{
   279  // 		To:   &ca,
   280  // 		Data: calldata,
   281  // 	}
   282  
   283  // 	p, _ := ethrpc.NewProvider("https://rinkeby.infura.io/v3/xxxx")
   284  // 	contractCallOutput, err := p.CallContract(context.Background(), txMsg, nil)
   285  // 	assert.NoError(t, err)
   286  
   287  // 	spew.Dump(contractCallOutput)
   288  
   289  // 	var values []*big.Int
   290  // 	err = AbiDecodeExpr("uint256[]", contractCallOutput, []interface{}{&values})
   291  // 	assert.NoError(t, err)
   292  
   293  // 	// spew.Dump(values)
   294  // }
   295  
   296  // func TestAbiContractCall2(t *testing.T) {
   297  // 	calldata, err := AbiEncodeMethodCalldataFromStringValues("getCurrencyReserves(uint256[])", []string{`["1","2","3"]`})
   298  // 	assert.NoError(t, err)
   299  // 	assert.Equal(t, "0x209b96c500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", HexEncode(calldata))
   300  
   301  // 	ca := common.HexToAddress("0xa519711c25a631e55a6eac19d1f2858c97a86a95")
   302  // 	txMsg := ethereum.CallMsg{
   303  // 		To:   &ca,
   304  // 		Data: calldata,
   305  // 	}
   306  
   307  // 	p, _ := ethrpc.NewProvider("https://rinkeby.infura.io/v3/xxxx")
   308  // 	contractCallOutput, err := p.CallContract(context.Background(), txMsg, nil)
   309  // 	assert.NoError(t, err)
   310  
   311  // 	spew.Dump(contractCallOutput)
   312  
   313  // 	values, err := AbiDecodeExprAndStringify("uint256[]", contractCallOutput)
   314  // 	assert.NoError(t, err)
   315  
   316  // 	spew.Dump(values)
   317  // }