github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/accounts/abi/abi_test.go (about)

     1  package abi
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"log"
     8  	"math/big"
     9  	"strings"
    10  	"testing"
    11  
    12  	"reflect"
    13  
    14  	"github.com/quickchainproject/quickchain/common"
    15  	"github.com/quickchainproject/quickchain/crypto"
    16  )
    17  
    18  const jsondata = `
    19  [
    20  	{ "type" : "function", "name" : "balance", "constant" : true },
    21  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
    22  ]`
    23  
    24  const jsondata2 = `
    25  [
    26  	{ "type" : "function", "name" : "balance", "constant" : true },
    27  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
    28  	{ "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
    29  	{ "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
    30  	{ "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
    31  	{ "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
    32  	{ "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
    33  	{ "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
    34  	{ "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
    35  	{ "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
    36  	{ "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
    37  	{ "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
    38  	{ "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
    39  	{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
    40  ]`
    41  
    42  func TestReader(t *testing.T) {
    43  	Uint256, _ := NewType("uint256")
    44  	exp := ABI{
    45  		Methods: map[string]Method{
    46  			"balance": {
    47  				"balance", true, nil, nil,
    48  			},
    49  			"send": {
    50  				"send", false, []Argument{
    51  					{"amount", Uint256, false},
    52  				}, nil,
    53  			},
    54  		},
    55  	}
    56  
    57  	abi, err := JSON(strings.NewReader(jsondata))
    58  	if err != nil {
    59  		t.Error(err)
    60  	}
    61  
    62  	// deep equal fails for some reason
    63  	for name, expM := range exp.Methods {
    64  		gotM, exist := abi.Methods[name]
    65  		if !exist {
    66  			t.Errorf("Missing expected method %v", name)
    67  		}
    68  		if !reflect.DeepEqual(gotM, expM) {
    69  			t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM)
    70  		}
    71  	}
    72  
    73  	for name, gotM := range abi.Methods {
    74  		expM, exist := exp.Methods[name]
    75  		if !exist {
    76  			t.Errorf("Found extra method %v", name)
    77  		}
    78  		if !reflect.DeepEqual(gotM, expM) {
    79  			t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM)
    80  		}
    81  	}
    82  }
    83  
    84  func TestTestNumbers(t *testing.T) {
    85  	abi, err := JSON(strings.NewReader(jsondata2))
    86  	if err != nil {
    87  		t.Error(err)
    88  		t.FailNow()
    89  	}
    90  
    91  	if _, err := abi.Pack("balance"); err != nil {
    92  		t.Error(err)
    93  	}
    94  
    95  	if _, err := abi.Pack("balance", 1); err == nil {
    96  		t.Error("expected error for balance(1)")
    97  	}
    98  
    99  	if _, err := abi.Pack("doesntexist", nil); err == nil {
   100  		t.Errorf("doesntexist shouldn't exist")
   101  	}
   102  
   103  	if _, err := abi.Pack("doesntexist", 1); err == nil {
   104  		t.Errorf("doesntexist(1) shouldn't exist")
   105  	}
   106  
   107  	if _, err := abi.Pack("send", big.NewInt(1000)); err != nil {
   108  		t.Error(err)
   109  	}
   110  
   111  	i := new(int)
   112  	*i = 1000
   113  	if _, err := abi.Pack("send", i); err == nil {
   114  		t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int")
   115  	}
   116  
   117  	if _, err := abi.Pack("test", uint32(1000)); err != nil {
   118  		t.Error(err)
   119  	}
   120  }
   121  
   122  func TestTestString(t *testing.T) {
   123  	abi, err := JSON(strings.NewReader(jsondata2))
   124  	if err != nil {
   125  		t.Error(err)
   126  		t.FailNow()
   127  	}
   128  
   129  	if _, err := abi.Pack("string", "hello world"); err != nil {
   130  		t.Error(err)
   131  	}
   132  }
   133  
   134  func TestTestBool(t *testing.T) {
   135  	abi, err := JSON(strings.NewReader(jsondata2))
   136  	if err != nil {
   137  		t.Error(err)
   138  		t.FailNow()
   139  	}
   140  
   141  	if _, err := abi.Pack("bool", true); err != nil {
   142  		t.Error(err)
   143  	}
   144  }
   145  
   146  func TestTestSlice(t *testing.T) {
   147  	abi, err := JSON(strings.NewReader(jsondata2))
   148  	if err != nil {
   149  		t.Error(err)
   150  		t.FailNow()
   151  	}
   152  
   153  	slice := make([]uint64, 2)
   154  	if _, err := abi.Pack("uint64[2]", slice); err != nil {
   155  		t.Error(err)
   156  	}
   157  
   158  	if _, err := abi.Pack("uint64[]", slice); err != nil {
   159  		t.Error(err)
   160  	}
   161  }
   162  
   163  func TestMethodSignature(t *testing.T) {
   164  	String, _ := NewType("string")
   165  	m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
   166  	exp := "foo(string,string)"
   167  	if m.Sig() != exp {
   168  		t.Error("signature mismatch", exp, "!=", m.Sig())
   169  	}
   170  
   171  	idexp := crypto.Keccak256([]byte(exp))[:4]
   172  	if !bytes.Equal(m.Id(), idexp) {
   173  		t.Errorf("expected ids to match %x != %x", m.Id(), idexp)
   174  	}
   175  
   176  	uintt, _ := NewType("uint256")
   177  	m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
   178  	exp = "foo(uint256)"
   179  	if m.Sig() != exp {
   180  		t.Error("signature mismatch", exp, "!=", m.Sig())
   181  	}
   182  }
   183  
   184  func TestMultiPack(t *testing.T) {
   185  	abi, err := JSON(strings.NewReader(jsondata2))
   186  	if err != nil {
   187  		t.Error(err)
   188  		t.FailNow()
   189  	}
   190  
   191  	sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4]
   192  	sig = append(sig, make([]byte, 64)...)
   193  	sig[35] = 10
   194  	sig[67] = 11
   195  
   196  	packed, err := abi.Pack("bar", uint32(10), uint16(11))
   197  	if err != nil {
   198  		t.Error(err)
   199  		t.FailNow()
   200  	}
   201  
   202  	if !bytes.Equal(packed, sig) {
   203  		t.Errorf("expected %x got %x", sig, packed)
   204  	}
   205  }
   206  
   207  func ExampleJSON() {
   208  	const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
   209  
   210  	abi, err := JSON(strings.NewReader(definition))
   211  	if err != nil {
   212  		log.Fatalln(err)
   213  	}
   214  	out, err := abi.Pack("isBar", common.HexToAddress("01"))
   215  	if err != nil {
   216  		log.Fatalln(err)
   217  	}
   218  
   219  	fmt.Printf("%x\n", out)
   220  	// Output:
   221  	// 1f2c40920000000000000000000000000000000000000000000000000000000000000001
   222  }
   223  
   224  func TestInputVariableInputLength(t *testing.T) {
   225  	const definition = `[
   226  	{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
   227  	{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
   228  	{ "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
   229  	]`
   230  
   231  	abi, err := JSON(strings.NewReader(definition))
   232  	if err != nil {
   233  		t.Fatal(err)
   234  	}
   235  
   236  	// test one string
   237  	strin := "hello world"
   238  	strpack, err := abi.Pack("strOne", strin)
   239  	if err != nil {
   240  		t.Error(err)
   241  	}
   242  
   243  	offset := make([]byte, 32)
   244  	offset[31] = 32
   245  	length := make([]byte, 32)
   246  	length[31] = byte(len(strin))
   247  	value := common.RightPadBytes([]byte(strin), 32)
   248  	exp := append(offset, append(length, value...)...)
   249  
   250  	// ignore first 4 bytes of the output. This is the function identifier
   251  	strpack = strpack[4:]
   252  	if !bytes.Equal(strpack, exp) {
   253  		t.Errorf("expected %x, got %x\n", exp, strpack)
   254  	}
   255  
   256  	// test one bytes
   257  	btspack, err := abi.Pack("bytesOne", []byte(strin))
   258  	if err != nil {
   259  		t.Error(err)
   260  	}
   261  	// ignore first 4 bytes of the output. This is the function identifier
   262  	btspack = btspack[4:]
   263  	if !bytes.Equal(btspack, exp) {
   264  		t.Errorf("expected %x, got %x\n", exp, btspack)
   265  	}
   266  
   267  	//  test two strings
   268  	str1 := "hello"
   269  	str2 := "world"
   270  	str2pack, err := abi.Pack("strTwo", str1, str2)
   271  	if err != nil {
   272  		t.Error(err)
   273  	}
   274  
   275  	offset1 := make([]byte, 32)
   276  	offset1[31] = 64
   277  	length1 := make([]byte, 32)
   278  	length1[31] = byte(len(str1))
   279  	value1 := common.RightPadBytes([]byte(str1), 32)
   280  
   281  	offset2 := make([]byte, 32)
   282  	offset2[31] = 128
   283  	length2 := make([]byte, 32)
   284  	length2[31] = byte(len(str2))
   285  	value2 := common.RightPadBytes([]byte(str2), 32)
   286  
   287  	exp2 := append(offset1, offset2...)
   288  	exp2 = append(exp2, append(length1, value1...)...)
   289  	exp2 = append(exp2, append(length2, value2...)...)
   290  
   291  	// ignore first 4 bytes of the output. This is the function identifier
   292  	str2pack = str2pack[4:]
   293  	if !bytes.Equal(str2pack, exp2) {
   294  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   295  	}
   296  
   297  	// test two strings, first > 32, second < 32
   298  	str1 = strings.Repeat("a", 33)
   299  	str2pack, err = abi.Pack("strTwo", str1, str2)
   300  	if err != nil {
   301  		t.Error(err)
   302  	}
   303  
   304  	offset1 = make([]byte, 32)
   305  	offset1[31] = 64
   306  	length1 = make([]byte, 32)
   307  	length1[31] = byte(len(str1))
   308  	value1 = common.RightPadBytes([]byte(str1), 64)
   309  	offset2[31] = 160
   310  
   311  	exp2 = append(offset1, offset2...)
   312  	exp2 = append(exp2, append(length1, value1...)...)
   313  	exp2 = append(exp2, append(length2, value2...)...)
   314  
   315  	// ignore first 4 bytes of the output. This is the function identifier
   316  	str2pack = str2pack[4:]
   317  	if !bytes.Equal(str2pack, exp2) {
   318  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   319  	}
   320  
   321  	// test two strings, first > 32, second >32
   322  	str1 = strings.Repeat("a", 33)
   323  	str2 = strings.Repeat("a", 33)
   324  	str2pack, err = abi.Pack("strTwo", str1, str2)
   325  	if err != nil {
   326  		t.Error(err)
   327  	}
   328  
   329  	offset1 = make([]byte, 32)
   330  	offset1[31] = 64
   331  	length1 = make([]byte, 32)
   332  	length1[31] = byte(len(str1))
   333  	value1 = common.RightPadBytes([]byte(str1), 64)
   334  
   335  	offset2 = make([]byte, 32)
   336  	offset2[31] = 160
   337  	length2 = make([]byte, 32)
   338  	length2[31] = byte(len(str2))
   339  	value2 = common.RightPadBytes([]byte(str2), 64)
   340  
   341  	exp2 = append(offset1, offset2...)
   342  	exp2 = append(exp2, append(length1, value1...)...)
   343  	exp2 = append(exp2, append(length2, value2...)...)
   344  
   345  	// ignore first 4 bytes of the output. This is the function identifier
   346  	str2pack = str2pack[4:]
   347  	if !bytes.Equal(str2pack, exp2) {
   348  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   349  	}
   350  }
   351  
   352  func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
   353  	const definition = `[
   354  	{ "type" : "function", "name" : "fixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
   355  	{ "type" : "function", "name" : "fixedArrBytes", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
   356      { "type" : "function", "name" : "mixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type": "uint256[2]" }, { "name" : "dynArr", "type": "uint256[]" } ] },
   357      { "type" : "function", "name" : "doubleFixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type": "uint256[2]" }, { "name" : "fixedArr2", "type": "uint256[3]" } ] },
   358      { "type" : "function", "name" : "multipleMixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type": "uint256[2]" }, { "name" : "dynArr", "type" : "uint256[]" }, { "name" : "fixedArr2", "type" : "uint256[3]" } ] }
   359  	]`
   360  
   361  	abi, err := JSON(strings.NewReader(definition))
   362  	if err != nil {
   363  		t.Error(err)
   364  	}
   365  
   366  	// test string, fixed array uint256[2]
   367  	strin := "hello world"
   368  	arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   369  	fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin)
   370  	if err != nil {
   371  		t.Error(err)
   372  	}
   373  
   374  	// generate expected output
   375  	offset := make([]byte, 32)
   376  	offset[31] = 96
   377  	length := make([]byte, 32)
   378  	length[31] = byte(len(strin))
   379  	strvalue := common.RightPadBytes([]byte(strin), 32)
   380  	arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32)
   381  	arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32)
   382  	exp := append(offset, arrinvalue1...)
   383  	exp = append(exp, arrinvalue2...)
   384  	exp = append(exp, append(length, strvalue...)...)
   385  
   386  	// ignore first 4 bytes of the output. This is the function identifier
   387  	fixedArrStrPack = fixedArrStrPack[4:]
   388  	if !bytes.Equal(fixedArrStrPack, exp) {
   389  		t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack)
   390  	}
   391  
   392  	// test byte array, fixed array uint256[2]
   393  	bytesin := []byte(strin)
   394  	arrin = [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   395  	fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin)
   396  	if err != nil {
   397  		t.Error(err)
   398  	}
   399  
   400  	// generate expected output
   401  	offset = make([]byte, 32)
   402  	offset[31] = 96
   403  	length = make([]byte, 32)
   404  	length[31] = byte(len(strin))
   405  	strvalue = common.RightPadBytes([]byte(strin), 32)
   406  	arrinvalue1 = common.LeftPadBytes(arrin[0].Bytes(), 32)
   407  	arrinvalue2 = common.LeftPadBytes(arrin[1].Bytes(), 32)
   408  	exp = append(offset, arrinvalue1...)
   409  	exp = append(exp, arrinvalue2...)
   410  	exp = append(exp, append(length, strvalue...)...)
   411  
   412  	// ignore first 4 bytes of the output. This is the function identifier
   413  	fixedArrBytesPack = fixedArrBytesPack[4:]
   414  	if !bytes.Equal(fixedArrBytesPack, exp) {
   415  		t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack)
   416  	}
   417  
   418  	// test string, fixed array uint256[2], dynamic array uint256[]
   419  	strin = "hello world"
   420  	fixedarrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   421  	dynarrin := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   422  	mixedArrStrPack, err := abi.Pack("mixedArrStr", strin, fixedarrin, dynarrin)
   423  	if err != nil {
   424  		t.Error(err)
   425  	}
   426  
   427  	// generate expected output
   428  	stroffset := make([]byte, 32)
   429  	stroffset[31] = 128
   430  	strlength := make([]byte, 32)
   431  	strlength[31] = byte(len(strin))
   432  	strvalue = common.RightPadBytes([]byte(strin), 32)
   433  	fixedarrinvalue1 := common.LeftPadBytes(fixedarrin[0].Bytes(), 32)
   434  	fixedarrinvalue2 := common.LeftPadBytes(fixedarrin[1].Bytes(), 32)
   435  	dynarroffset := make([]byte, 32)
   436  	dynarroffset[31] = byte(160 + ((len(strin)/32)+1)*32)
   437  	dynarrlength := make([]byte, 32)
   438  	dynarrlength[31] = byte(len(dynarrin))
   439  	dynarrinvalue1 := common.LeftPadBytes(dynarrin[0].Bytes(), 32)
   440  	dynarrinvalue2 := common.LeftPadBytes(dynarrin[1].Bytes(), 32)
   441  	dynarrinvalue3 := common.LeftPadBytes(dynarrin[2].Bytes(), 32)
   442  	exp = append(stroffset, fixedarrinvalue1...)
   443  	exp = append(exp, fixedarrinvalue2...)
   444  	exp = append(exp, dynarroffset...)
   445  	exp = append(exp, append(strlength, strvalue...)...)
   446  	dynarrarg := append(dynarrlength, dynarrinvalue1...)
   447  	dynarrarg = append(dynarrarg, dynarrinvalue2...)
   448  	dynarrarg = append(dynarrarg, dynarrinvalue3...)
   449  	exp = append(exp, dynarrarg...)
   450  
   451  	// ignore first 4 bytes of the output. This is the function identifier
   452  	mixedArrStrPack = mixedArrStrPack[4:]
   453  	if !bytes.Equal(mixedArrStrPack, exp) {
   454  		t.Errorf("expected %x, got %x\n", exp, mixedArrStrPack)
   455  	}
   456  
   457  	// test string, fixed array uint256[2], fixed array uint256[3]
   458  	strin = "hello world"
   459  	fixedarrin1 := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   460  	fixedarrin2 := [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   461  	doubleFixedArrStrPack, err := abi.Pack("doubleFixedArrStr", strin, fixedarrin1, fixedarrin2)
   462  	if err != nil {
   463  		t.Error(err)
   464  	}
   465  
   466  	// generate expected output
   467  	stroffset = make([]byte, 32)
   468  	stroffset[31] = 192
   469  	strlength = make([]byte, 32)
   470  	strlength[31] = byte(len(strin))
   471  	strvalue = common.RightPadBytes([]byte(strin), 32)
   472  	fixedarrin1value1 := common.LeftPadBytes(fixedarrin1[0].Bytes(), 32)
   473  	fixedarrin1value2 := common.LeftPadBytes(fixedarrin1[1].Bytes(), 32)
   474  	fixedarrin2value1 := common.LeftPadBytes(fixedarrin2[0].Bytes(), 32)
   475  	fixedarrin2value2 := common.LeftPadBytes(fixedarrin2[1].Bytes(), 32)
   476  	fixedarrin2value3 := common.LeftPadBytes(fixedarrin2[2].Bytes(), 32)
   477  	exp = append(stroffset, fixedarrin1value1...)
   478  	exp = append(exp, fixedarrin1value2...)
   479  	exp = append(exp, fixedarrin2value1...)
   480  	exp = append(exp, fixedarrin2value2...)
   481  	exp = append(exp, fixedarrin2value3...)
   482  	exp = append(exp, append(strlength, strvalue...)...)
   483  
   484  	// ignore first 4 bytes of the output. This is the function identifier
   485  	doubleFixedArrStrPack = doubleFixedArrStrPack[4:]
   486  	if !bytes.Equal(doubleFixedArrStrPack, exp) {
   487  		t.Errorf("expected %x, got %x\n", exp, doubleFixedArrStrPack)
   488  	}
   489  
   490  	// test string, fixed array uint256[2], dynamic array uint256[], fixed array uint256[3]
   491  	strin = "hello world"
   492  	fixedarrin1 = [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   493  	dynarrin = []*big.Int{big.NewInt(1), big.NewInt(2)}
   494  	fixedarrin2 = [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   495  	multipleMixedArrStrPack, err := abi.Pack("multipleMixedArrStr", strin, fixedarrin1, dynarrin, fixedarrin2)
   496  	if err != nil {
   497  		t.Error(err)
   498  	}
   499  
   500  	// generate expected output
   501  	stroffset = make([]byte, 32)
   502  	stroffset[31] = 224
   503  	strlength = make([]byte, 32)
   504  	strlength[31] = byte(len(strin))
   505  	strvalue = common.RightPadBytes([]byte(strin), 32)
   506  	fixedarrin1value1 = common.LeftPadBytes(fixedarrin1[0].Bytes(), 32)
   507  	fixedarrin1value2 = common.LeftPadBytes(fixedarrin1[1].Bytes(), 32)
   508  	dynarroffset = U256(big.NewInt(int64(256 + ((len(strin)/32)+1)*32)))
   509  	dynarrlength = make([]byte, 32)
   510  	dynarrlength[31] = byte(len(dynarrin))
   511  	dynarrinvalue1 = common.LeftPadBytes(dynarrin[0].Bytes(), 32)
   512  	dynarrinvalue2 = common.LeftPadBytes(dynarrin[1].Bytes(), 32)
   513  	fixedarrin2value1 = common.LeftPadBytes(fixedarrin2[0].Bytes(), 32)
   514  	fixedarrin2value2 = common.LeftPadBytes(fixedarrin2[1].Bytes(), 32)
   515  	fixedarrin2value3 = common.LeftPadBytes(fixedarrin2[2].Bytes(), 32)
   516  	exp = append(stroffset, fixedarrin1value1...)
   517  	exp = append(exp, fixedarrin1value2...)
   518  	exp = append(exp, dynarroffset...)
   519  	exp = append(exp, fixedarrin2value1...)
   520  	exp = append(exp, fixedarrin2value2...)
   521  	exp = append(exp, fixedarrin2value3...)
   522  	exp = append(exp, append(strlength, strvalue...)...)
   523  	dynarrarg = append(dynarrlength, dynarrinvalue1...)
   524  	dynarrarg = append(dynarrarg, dynarrinvalue2...)
   525  	exp = append(exp, dynarrarg...)
   526  
   527  	// ignore first 4 bytes of the output. This is the function identifier
   528  	multipleMixedArrStrPack = multipleMixedArrStrPack[4:]
   529  	if !bytes.Equal(multipleMixedArrStrPack, exp) {
   530  		t.Errorf("expected %x, got %x\n", exp, multipleMixedArrStrPack)
   531  	}
   532  }
   533  
   534  func TestDefaultFunctionParsing(t *testing.T) {
   535  	const definition = `[{ "name" : "balance" }]`
   536  
   537  	abi, err := JSON(strings.NewReader(definition))
   538  	if err != nil {
   539  		t.Fatal(err)
   540  	}
   541  
   542  	if _, ok := abi.Methods["balance"]; !ok {
   543  		t.Error("expected 'balance' to be present")
   544  	}
   545  }
   546  
   547  func TestBareEvents(t *testing.T) {
   548  	const definition = `[
   549  	{ "type" : "event", "name" : "balance" },
   550  	{ "type" : "event", "name" : "anon", "anonymous" : true},
   551  	{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }
   552  	]`
   553  
   554  	arg0, _ := NewType("uint256")
   555  	arg1, _ := NewType("address")
   556  
   557  	expectedEvents := map[string]struct {
   558  		Anonymous bool
   559  		Args      []Argument
   560  	}{
   561  		"balance": {false, nil},
   562  		"anon":    {true, nil},
   563  		"args": {false, []Argument{
   564  			{Name: "arg0", Type: arg0, Indexed: false},
   565  			{Name: "arg1", Type: arg1, Indexed: true},
   566  		}},
   567  	}
   568  
   569  	abi, err := JSON(strings.NewReader(definition))
   570  	if err != nil {
   571  		t.Fatal(err)
   572  	}
   573  
   574  	if len(abi.Events) != len(expectedEvents) {
   575  		t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events))
   576  	}
   577  
   578  	for name, exp := range expectedEvents {
   579  		got, ok := abi.Events[name]
   580  		if !ok {
   581  			t.Errorf("could not found event %s", name)
   582  			continue
   583  		}
   584  		if got.Anonymous != exp.Anonymous {
   585  			t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous)
   586  		}
   587  		if len(got.Inputs) != len(exp.Args) {
   588  			t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs))
   589  			continue
   590  		}
   591  		for i, arg := range exp.Args {
   592  			if arg.Name != got.Inputs[i].Name {
   593  				t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name)
   594  			}
   595  			if arg.Indexed != got.Inputs[i].Indexed {
   596  				t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed)
   597  			}
   598  			if arg.Type.T != got.Inputs[i].Type.T {
   599  				t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T)
   600  			}
   601  		}
   602  	}
   603  }
   604  
   605  // TestUnpackEvent is based on this contract:
   606  //    contract T {
   607  //      event received(address sender, uint amount, bytes memo);
   608  //      event receivedAddr(address sender);
   609  //      function receive(bytes memo) external payable {
   610  //        received(msg.sender, msg.value, memo);
   611  //        receivedAddr(msg.sender);
   612  //      }
   613  //    }
   614  // When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
   615  //   receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
   616  func TestUnpackEvent(t *testing.T) {
   617  	const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
   618  	abi, err := JSON(strings.NewReader(abiJSON))
   619  	if err != nil {
   620  		t.Fatal(err)
   621  	}
   622  
   623  	const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
   624  	data, err := hex.DecodeString(hexdata)
   625  	if err != nil {
   626  		t.Fatal(err)
   627  	}
   628  	if len(data)%32 == 0 {
   629  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   630  	}
   631  
   632  	type ReceivedEvent struct {
   633  		Address common.Address
   634  		Amount  *big.Int
   635  		Memo    []byte
   636  	}
   637  	var ev ReceivedEvent
   638  
   639  	err = abi.Unpack(&ev, "received", data)
   640  	if err != nil {
   641  		t.Error(err)
   642  	} else {
   643  		t.Logf("len(data): %d; received event: %+v", len(data), ev)
   644  	}
   645  
   646  	type ReceivedAddrEvent struct {
   647  		Address common.Address
   648  	}
   649  	var receivedAddrEv ReceivedAddrEvent
   650  	err = abi.Unpack(&receivedAddrEv, "receivedAddr", data)
   651  	if err != nil {
   652  		t.Error(err)
   653  	} else {
   654  		t.Logf("len(data): %d; received event: %+v", len(data), receivedAddrEv)
   655  	}
   656  }
   657  
   658  func TestABI_MethodById(t *testing.T) {
   659  	const abiJSON = `[
   660  		{"type":"function","name":"receive","constant":false,"inputs":[{"name":"memo","type":"bytes"}],"outputs":[],"payable":true,"stateMutability":"payable"},
   661  		{"type":"event","name":"received","anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}]},
   662  		{"type":"function","name":"fixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"}]},
   663  		{"type":"function","name":"fixedArrBytes","constant":true,"inputs":[{"name":"str","type":"bytes"},{"name":"fixedArr","type":"uint256[2]"}]},
   664  		{"type":"function","name":"mixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"},{"name":"dynArr","type":"uint256[]"}]},
   665  		{"type":"function","name":"doubleFixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr1","type":"uint256[2]"},{"name":"fixedArr2","type":"uint256[3]"}]},
   666  		{"type":"function","name":"multipleMixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr1","type":"uint256[2]"},{"name":"dynArr","type":"uint256[]"},{"name":"fixedArr2","type":"uint256[3]"}]},
   667  		{"type":"function","name":"balance","constant":true},
   668  		{"type":"function","name":"send","constant":false,"inputs":[{"name":"amount","type":"uint256"}]},
   669  		{"type":"function","name":"test","constant":false,"inputs":[{"name":"number","type":"uint32"}]},
   670  		{"type":"function","name":"string","constant":false,"inputs":[{"name":"inputs","type":"string"}]},
   671  		{"type":"function","name":"bool","constant":false,"inputs":[{"name":"inputs","type":"bool"}]},
   672  		{"type":"function","name":"address","constant":false,"inputs":[{"name":"inputs","type":"address"}]},
   673  		{"type":"function","name":"uint64[2]","constant":false,"inputs":[{"name":"inputs","type":"uint64[2]"}]},
   674  		{"type":"function","name":"uint64[]","constant":false,"inputs":[{"name":"inputs","type":"uint64[]"}]},
   675  		{"type":"function","name":"foo","constant":false,"inputs":[{"name":"inputs","type":"uint32"}]},
   676  		{"type":"function","name":"bar","constant":false,"inputs":[{"name":"inputs","type":"uint32"},{"name":"string","type":"uint16"}]},
   677  		{"type":"function","name":"_slice","constant":false,"inputs":[{"name":"inputs","type":"uint32[2]"}]},
   678  		{"type":"function","name":"__slice256","constant":false,"inputs":[{"name":"inputs","type":"uint256[2]"}]},
   679  		{"type":"function","name":"sliceAddress","constant":false,"inputs":[{"name":"inputs","type":"address[]"}]},
   680  		{"type":"function","name":"sliceMultiAddress","constant":false,"inputs":[{"name":"a","type":"address[]"},{"name":"b","type":"address[]"}]}
   681  	]
   682  `
   683  	abi, err := JSON(strings.NewReader(abiJSON))
   684  	if err != nil {
   685  		t.Fatal(err)
   686  	}
   687  	for name, m := range abi.Methods {
   688  		a := fmt.Sprintf("%v", m)
   689  		m2, err := abi.MethodById(m.Id())
   690  		if err != nil {
   691  			t.Fatalf("Failed to look up ABI method: %v", err)
   692  		}
   693  		b := fmt.Sprintf("%v", m2)
   694  		if a != b {
   695  			t.Errorf("Method %v (id %v) not 'findable' by id in ABI", name, common.ToHex(m.Id()))
   696  		}
   697  	}
   698  
   699  }