github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/accounts/abi/abi_test.go (about)

     1  package abi
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"math/big"
     8  	"strings"
     9  	"testing"
    10  
    11  	"reflect"
    12  
    13  	"github.com/neatio-net/neatio/utilities/common"
    14  	"github.com/neatio-net/neatio/utilities/crypto"
    15  )
    16  
    17  const jsondata = `
    18  [
    19  	{ "type" : "function", "name" : "balance", "constant" : true },
    20  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
    21  ]`
    22  
    23  const jsondata2 = `
    24  [
    25  	{ "type" : "function", "name" : "balance", "constant" : true },
    26  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
    27  	{ "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
    28  	{ "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
    29  	{ "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
    30  	{ "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
    31  	{ "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
    32  	{ "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
    33  	{ "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
    34  	{ "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
    35  	{ "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
    36  	{ "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
    37  	{ "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
    38  	{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] },
    39  	{ "type" : "function", "name" : "nestedArray", "constant" : false, "inputs" : [ { "name" : "a", "type" : "uint256[2][2]" }, { "name" : "b", "type" : "address[]" } ] },
    40  	{ "type" : "function", "name" : "nestedArray2", "constant" : false, "inputs" : [ { "name" : "a", "type" : "uint8[][2]" } ] },
    41  	{ "type" : "function", "name" : "nestedSlice", "constant" : false, "inputs" : [ { "name" : "a", "type" : "uint8[][]" } ] }
    42  ]`
    43  
    44  func TestReader(t *testing.T) {
    45  	Uint256, _ := NewType("uint256", "", nil)
    46  	exp := ABI{
    47  		Methods: map[string]Method{
    48  			"balance": {
    49  				"balance", "balance", true, nil, nil,
    50  			},
    51  			"send": {
    52  				"send", "send", false, []Argument{
    53  					{"amount", Uint256, false},
    54  				}, nil,
    55  			},
    56  		},
    57  	}
    58  
    59  	abi, err := JSON(strings.NewReader(jsondata))
    60  	if err != nil {
    61  		t.Error(err)
    62  	}
    63  
    64  	for name, expM := range exp.Methods {
    65  		gotM, exist := abi.Methods[name]
    66  		if !exist {
    67  			t.Errorf("Missing expected method %v", name)
    68  		}
    69  		if !reflect.DeepEqual(gotM, expM) {
    70  			t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM)
    71  		}
    72  	}
    73  
    74  	for name, gotM := range abi.Methods {
    75  		expM, exist := exp.Methods[name]
    76  		if !exist {
    77  			t.Errorf("Found extra method %v", name)
    78  		}
    79  		if !reflect.DeepEqual(gotM, expM) {
    80  			t.Errorf("\nGot abi method: \n%v\ndoes not match expected method\n%v", gotM, expM)
    81  		}
    82  	}
    83  }
    84  
    85  func TestTestNumbers(t *testing.T) {
    86  	abi, err := JSON(strings.NewReader(jsondata2))
    87  	if err != nil {
    88  		t.Fatal(err)
    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.Fatal(err)
   126  	}
   127  
   128  	if _, err := abi.Pack("string", "hello world"); err != nil {
   129  		t.Error(err)
   130  	}
   131  }
   132  
   133  func TestTestBool(t *testing.T) {
   134  	abi, err := JSON(strings.NewReader(jsondata2))
   135  	if err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	if _, err := abi.Pack("bool", true); err != nil {
   140  		t.Error(err)
   141  	}
   142  }
   143  
   144  func TestTestSlice(t *testing.T) {
   145  	abi, err := JSON(strings.NewReader(jsondata2))
   146  	if err != nil {
   147  		t.Fatal(err)
   148  	}
   149  	slice := make([]uint64, 2)
   150  	if _, err := abi.Pack("uint64[2]", slice); err != nil {
   151  		t.Error(err)
   152  	}
   153  	if _, err := abi.Pack("uint64[]", slice); err != nil {
   154  		t.Error(err)
   155  	}
   156  }
   157  
   158  func TestMethodSignature(t *testing.T) {
   159  	String, _ := NewType("string", "", nil)
   160  	m := Method{"foo", "foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
   161  	exp := "foo(string,string)"
   162  	if m.Sig() != exp {
   163  		t.Error("signature mismatch", exp, "!=", m.Sig())
   164  	}
   165  
   166  	idexp := crypto.Keccak256([]byte(exp))[:4]
   167  	if !bytes.Equal(m.ID(), idexp) {
   168  		t.Errorf("expected ids to match %x != %x", m.ID(), idexp)
   169  	}
   170  
   171  	uintt, _ := NewType("uint256", "", nil)
   172  	m = Method{"foo", "foo", false, []Argument{{"bar", uintt, false}}, nil}
   173  	exp = "foo(uint256)"
   174  	if m.Sig() != exp {
   175  		t.Error("signature mismatch", exp, "!=", m.Sig())
   176  	}
   177  
   178  	s, _ := NewType("tuple", "", []ArgumentMarshaling{
   179  		{Name: "a", Type: "int256"},
   180  		{Name: "b", Type: "int256[]"},
   181  		{Name: "c", Type: "tuple[]", Components: []ArgumentMarshaling{
   182  			{Name: "x", Type: "int256"},
   183  			{Name: "y", Type: "int256"},
   184  		}},
   185  		{Name: "d", Type: "tuple[2]", Components: []ArgumentMarshaling{
   186  			{Name: "x", Type: "int256"},
   187  			{Name: "y", Type: "int256"},
   188  		}},
   189  	})
   190  	m = Method{"foo", "foo", false, []Argument{{"s", s, false}, {"bar", String, false}}, nil}
   191  	exp = "foo((int256,int256[],(int256,int256)[],(int256,int256)[2]),string)"
   192  	if m.Sig() != exp {
   193  		t.Error("signature mismatch", exp, "!=", m.Sig())
   194  	}
   195  }
   196  
   197  func TestOverloadedMethodSignature(t *testing.T) {
   198  	json := `[{"constant":true,"inputs":[{"name":"i","type":"uint256"},{"name":"j","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"i","type":"uint256"}],"name":"foo","outputs":[],"payable":false,"stateMutability":"pure","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"}],"name":"bar","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"i","type":"uint256"},{"indexed":false,"name":"j","type":"uint256"}],"name":"bar","type":"event"}]`
   199  	abi, err := JSON(strings.NewReader(json))
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	check := func(name string, expect string, method bool) {
   204  		if method {
   205  			if abi.Methods[name].Sig() != expect {
   206  				t.Fatalf("The signature of overloaded method mismatch, want %s, have %s", expect, abi.Methods[name].Sig())
   207  			}
   208  		} else {
   209  			if abi.Events[name].Sig() != expect {
   210  				t.Fatalf("The signature of overloaded event mismatch, want %s, have %s", expect, abi.Events[name].Sig())
   211  			}
   212  		}
   213  	}
   214  	check("foo", "foo(uint256,uint256)", true)
   215  	check("foo0", "foo(uint256)", true)
   216  	check("bar", "bar(uint256)", false)
   217  	check("bar0", "bar(uint256,uint256)", false)
   218  }
   219  
   220  func TestMultiPack(t *testing.T) {
   221  	abi, err := JSON(strings.NewReader(jsondata2))
   222  	if err != nil {
   223  		t.Fatal(err)
   224  	}
   225  
   226  	sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4]
   227  	sig = append(sig, make([]byte, 64)...)
   228  	sig[35] = 10
   229  	sig[67] = 11
   230  
   231  	packed, err := abi.Pack("bar", uint32(10), uint16(11))
   232  	if err != nil {
   233  		t.Fatal(err)
   234  	}
   235  	if !bytes.Equal(packed, sig) {
   236  		t.Errorf("expected %x got %x", sig, packed)
   237  	}
   238  }
   239  
   240  func ExampleJSON() {
   241  	const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
   242  
   243  	abi, err := JSON(strings.NewReader(definition))
   244  	if err != nil {
   245  		panic(err)
   246  	}
   247  	out, err := abi.Pack("isBar", common.HexToAddress("01"))
   248  	if err != nil {
   249  		panic(err)
   250  	}
   251  
   252  	fmt.Printf("%x\n", out)
   253  
   254  }
   255  
   256  func TestInputVariableInputLength(t *testing.T) {
   257  	const definition = `[
   258  	{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
   259  	{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
   260  	{ "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
   261  	]`
   262  
   263  	abi, err := JSON(strings.NewReader(definition))
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  
   268  	strin := "hello world"
   269  	strpack, err := abi.Pack("strOne", strin)
   270  	if err != nil {
   271  		t.Error(err)
   272  	}
   273  
   274  	offset := make([]byte, 32)
   275  	offset[31] = 32
   276  	length := make([]byte, 32)
   277  	length[31] = byte(len(strin))
   278  	value := common.RightPadBytes([]byte(strin), 32)
   279  	exp := append(offset, append(length, value...)...)
   280  
   281  	strpack = strpack[4:]
   282  	if !bytes.Equal(strpack, exp) {
   283  		t.Errorf("expected %x, got %x\n", exp, strpack)
   284  	}
   285  
   286  	btspack, err := abi.Pack("bytesOne", []byte(strin))
   287  	if err != nil {
   288  		t.Error(err)
   289  	}
   290  
   291  	btspack = btspack[4:]
   292  	if !bytes.Equal(btspack, exp) {
   293  		t.Errorf("expected %x, got %x\n", exp, btspack)
   294  	}
   295  
   296  	str1 := "hello"
   297  	str2 := "world"
   298  	str2pack, err := abi.Pack("strTwo", str1, str2)
   299  	if err != nil {
   300  		t.Error(err)
   301  	}
   302  
   303  	offset1 := make([]byte, 32)
   304  	offset1[31] = 64
   305  	length1 := make([]byte, 32)
   306  	length1[31] = byte(len(str1))
   307  	value1 := common.RightPadBytes([]byte(str1), 32)
   308  
   309  	offset2 := make([]byte, 32)
   310  	offset2[31] = 128
   311  	length2 := make([]byte, 32)
   312  	length2[31] = byte(len(str2))
   313  	value2 := common.RightPadBytes([]byte(str2), 32)
   314  
   315  	exp2 := append(offset1, offset2...)
   316  	exp2 = append(exp2, append(length1, value1...)...)
   317  	exp2 = append(exp2, append(length2, value2...)...)
   318  
   319  	str2pack = str2pack[4:]
   320  	if !bytes.Equal(str2pack, exp2) {
   321  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   322  	}
   323  
   324  	str1 = strings.Repeat("a", 33)
   325  	str2pack, err = abi.Pack("strTwo", str1, str2)
   326  	if err != nil {
   327  		t.Error(err)
   328  	}
   329  
   330  	offset1 = make([]byte, 32)
   331  	offset1[31] = 64
   332  	length1 = make([]byte, 32)
   333  	length1[31] = byte(len(str1))
   334  	value1 = common.RightPadBytes([]byte(str1), 64)
   335  	offset2[31] = 160
   336  
   337  	exp2 = append(offset1, offset2...)
   338  	exp2 = append(exp2, append(length1, value1...)...)
   339  	exp2 = append(exp2, append(length2, value2...)...)
   340  
   341  	str2pack = str2pack[4:]
   342  	if !bytes.Equal(str2pack, exp2) {
   343  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   344  	}
   345  
   346  	str1 = strings.Repeat("a", 33)
   347  	str2 = strings.Repeat("a", 33)
   348  	str2pack, err = abi.Pack("strTwo", str1, str2)
   349  	if err != nil {
   350  		t.Error(err)
   351  	}
   352  
   353  	offset1 = make([]byte, 32)
   354  	offset1[31] = 64
   355  	length1 = make([]byte, 32)
   356  	length1[31] = byte(len(str1))
   357  	value1 = common.RightPadBytes([]byte(str1), 64)
   358  
   359  	offset2 = make([]byte, 32)
   360  	offset2[31] = 160
   361  	length2 = make([]byte, 32)
   362  	length2[31] = byte(len(str2))
   363  	value2 = common.RightPadBytes([]byte(str2), 64)
   364  
   365  	exp2 = append(offset1, offset2...)
   366  	exp2 = append(exp2, append(length1, value1...)...)
   367  	exp2 = append(exp2, append(length2, value2...)...)
   368  
   369  	str2pack = str2pack[4:]
   370  	if !bytes.Equal(str2pack, exp2) {
   371  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   372  	}
   373  }
   374  
   375  func TestInputFixedArrayAndVariableInputLength(t *testing.T) {
   376  	const definition = `[
   377  	{ "type" : "function", "name" : "fixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
   378  	{ "type" : "function", "name" : "fixedArrBytes", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" }, { "name" : "fixedArr", "type" : "uint256[2]" } ] },
   379      { "type" : "function", "name" : "mixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr", "type": "uint256[2]" }, { "name" : "dynArr", "type": "uint256[]" } ] },
   380      { "type" : "function", "name" : "doubleFixedArrStr", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "fixedArr1", "type": "uint256[2]" }, { "name" : "fixedArr2", "type": "uint256[3]" } ] },
   381      { "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]" } ] }
   382  	]`
   383  
   384  	abi, err := JSON(strings.NewReader(definition))
   385  	if err != nil {
   386  		t.Error(err)
   387  	}
   388  
   389  	strin := "hello world"
   390  	arrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   391  	fixedArrStrPack, err := abi.Pack("fixedArrStr", strin, arrin)
   392  	if err != nil {
   393  		t.Error(err)
   394  	}
   395  
   396  	offset := make([]byte, 32)
   397  	offset[31] = 96
   398  	length := make([]byte, 32)
   399  	length[31] = byte(len(strin))
   400  	strvalue := common.RightPadBytes([]byte(strin), 32)
   401  	arrinvalue1 := common.LeftPadBytes(arrin[0].Bytes(), 32)
   402  	arrinvalue2 := common.LeftPadBytes(arrin[1].Bytes(), 32)
   403  	exp := append(offset, arrinvalue1...)
   404  	exp = append(exp, arrinvalue2...)
   405  	exp = append(exp, append(length, strvalue...)...)
   406  
   407  	fixedArrStrPack = fixedArrStrPack[4:]
   408  	if !bytes.Equal(fixedArrStrPack, exp) {
   409  		t.Errorf("expected %x, got %x\n", exp, fixedArrStrPack)
   410  	}
   411  
   412  	bytesin := []byte(strin)
   413  	arrin = [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   414  	fixedArrBytesPack, err := abi.Pack("fixedArrBytes", bytesin, arrin)
   415  	if err != nil {
   416  		t.Error(err)
   417  	}
   418  
   419  	offset = make([]byte, 32)
   420  	offset[31] = 96
   421  	length = make([]byte, 32)
   422  	length[31] = byte(len(strin))
   423  	strvalue = common.RightPadBytes([]byte(strin), 32)
   424  	arrinvalue1 = common.LeftPadBytes(arrin[0].Bytes(), 32)
   425  	arrinvalue2 = common.LeftPadBytes(arrin[1].Bytes(), 32)
   426  	exp = append(offset, arrinvalue1...)
   427  	exp = append(exp, arrinvalue2...)
   428  	exp = append(exp, append(length, strvalue...)...)
   429  
   430  	fixedArrBytesPack = fixedArrBytesPack[4:]
   431  	if !bytes.Equal(fixedArrBytesPack, exp) {
   432  		t.Errorf("expected %x, got %x\n", exp, fixedArrBytesPack)
   433  	}
   434  
   435  	strin = "hello world"
   436  	fixedarrin := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   437  	dynarrin := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   438  	mixedArrStrPack, err := abi.Pack("mixedArrStr", strin, fixedarrin, dynarrin)
   439  	if err != nil {
   440  		t.Error(err)
   441  	}
   442  
   443  	stroffset := make([]byte, 32)
   444  	stroffset[31] = 128
   445  	strlength := make([]byte, 32)
   446  	strlength[31] = byte(len(strin))
   447  	strvalue = common.RightPadBytes([]byte(strin), 32)
   448  	fixedarrinvalue1 := common.LeftPadBytes(fixedarrin[0].Bytes(), 32)
   449  	fixedarrinvalue2 := common.LeftPadBytes(fixedarrin[1].Bytes(), 32)
   450  	dynarroffset := make([]byte, 32)
   451  	dynarroffset[31] = byte(160 + ((len(strin)/32)+1)*32)
   452  	dynarrlength := make([]byte, 32)
   453  	dynarrlength[31] = byte(len(dynarrin))
   454  	dynarrinvalue1 := common.LeftPadBytes(dynarrin[0].Bytes(), 32)
   455  	dynarrinvalue2 := common.LeftPadBytes(dynarrin[1].Bytes(), 32)
   456  	dynarrinvalue3 := common.LeftPadBytes(dynarrin[2].Bytes(), 32)
   457  	exp = append(stroffset, fixedarrinvalue1...)
   458  	exp = append(exp, fixedarrinvalue2...)
   459  	exp = append(exp, dynarroffset...)
   460  	exp = append(exp, append(strlength, strvalue...)...)
   461  	dynarrarg := append(dynarrlength, dynarrinvalue1...)
   462  	dynarrarg = append(dynarrarg, dynarrinvalue2...)
   463  	dynarrarg = append(dynarrarg, dynarrinvalue3...)
   464  	exp = append(exp, dynarrarg...)
   465  
   466  	mixedArrStrPack = mixedArrStrPack[4:]
   467  	if !bytes.Equal(mixedArrStrPack, exp) {
   468  		t.Errorf("expected %x, got %x\n", exp, mixedArrStrPack)
   469  	}
   470  
   471  	strin = "hello world"
   472  	fixedarrin1 := [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   473  	fixedarrin2 := [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   474  	doubleFixedArrStrPack, err := abi.Pack("doubleFixedArrStr", strin, fixedarrin1, fixedarrin2)
   475  	if err != nil {
   476  		t.Error(err)
   477  	}
   478  
   479  	stroffset = make([]byte, 32)
   480  	stroffset[31] = 192
   481  	strlength = make([]byte, 32)
   482  	strlength[31] = byte(len(strin))
   483  	strvalue = common.RightPadBytes([]byte(strin), 32)
   484  	fixedarrin1value1 := common.LeftPadBytes(fixedarrin1[0].Bytes(), 32)
   485  	fixedarrin1value2 := common.LeftPadBytes(fixedarrin1[1].Bytes(), 32)
   486  	fixedarrin2value1 := common.LeftPadBytes(fixedarrin2[0].Bytes(), 32)
   487  	fixedarrin2value2 := common.LeftPadBytes(fixedarrin2[1].Bytes(), 32)
   488  	fixedarrin2value3 := common.LeftPadBytes(fixedarrin2[2].Bytes(), 32)
   489  	exp = append(stroffset, fixedarrin1value1...)
   490  	exp = append(exp, fixedarrin1value2...)
   491  	exp = append(exp, fixedarrin2value1...)
   492  	exp = append(exp, fixedarrin2value2...)
   493  	exp = append(exp, fixedarrin2value3...)
   494  	exp = append(exp, append(strlength, strvalue...)...)
   495  
   496  	doubleFixedArrStrPack = doubleFixedArrStrPack[4:]
   497  	if !bytes.Equal(doubleFixedArrStrPack, exp) {
   498  		t.Errorf("expected %x, got %x\n", exp, doubleFixedArrStrPack)
   499  	}
   500  
   501  	strin = "hello world"
   502  	fixedarrin1 = [2]*big.Int{big.NewInt(1), big.NewInt(2)}
   503  	dynarrin = []*big.Int{big.NewInt(1), big.NewInt(2)}
   504  	fixedarrin2 = [3]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}
   505  	multipleMixedArrStrPack, err := abi.Pack("multipleMixedArrStr", strin, fixedarrin1, dynarrin, fixedarrin2)
   506  	if err != nil {
   507  		t.Error(err)
   508  	}
   509  
   510  	stroffset = make([]byte, 32)
   511  	stroffset[31] = 224
   512  	strlength = make([]byte, 32)
   513  	strlength[31] = byte(len(strin))
   514  	strvalue = common.RightPadBytes([]byte(strin), 32)
   515  	fixedarrin1value1 = common.LeftPadBytes(fixedarrin1[0].Bytes(), 32)
   516  	fixedarrin1value2 = common.LeftPadBytes(fixedarrin1[1].Bytes(), 32)
   517  	dynarroffset = U256(big.NewInt(int64(256 + ((len(strin)/32)+1)*32)))
   518  	dynarrlength = make([]byte, 32)
   519  	dynarrlength[31] = byte(len(dynarrin))
   520  	dynarrinvalue1 = common.LeftPadBytes(dynarrin[0].Bytes(), 32)
   521  	dynarrinvalue2 = common.LeftPadBytes(dynarrin[1].Bytes(), 32)
   522  	fixedarrin2value1 = common.LeftPadBytes(fixedarrin2[0].Bytes(), 32)
   523  	fixedarrin2value2 = common.LeftPadBytes(fixedarrin2[1].Bytes(), 32)
   524  	fixedarrin2value3 = common.LeftPadBytes(fixedarrin2[2].Bytes(), 32)
   525  	exp = append(stroffset, fixedarrin1value1...)
   526  	exp = append(exp, fixedarrin1value2...)
   527  	exp = append(exp, dynarroffset...)
   528  	exp = append(exp, fixedarrin2value1...)
   529  	exp = append(exp, fixedarrin2value2...)
   530  	exp = append(exp, fixedarrin2value3...)
   531  	exp = append(exp, append(strlength, strvalue...)...)
   532  	dynarrarg = append(dynarrlength, dynarrinvalue1...)
   533  	dynarrarg = append(dynarrarg, dynarrinvalue2...)
   534  	exp = append(exp, dynarrarg...)
   535  
   536  	multipleMixedArrStrPack = multipleMixedArrStrPack[4:]
   537  	if !bytes.Equal(multipleMixedArrStrPack, exp) {
   538  		t.Errorf("expected %x, got %x\n", exp, multipleMixedArrStrPack)
   539  	}
   540  }
   541  
   542  func TestDefaultFunctionParsing(t *testing.T) {
   543  	const definition = `[{ "name" : "balance" }]`
   544  
   545  	abi, err := JSON(strings.NewReader(definition))
   546  	if err != nil {
   547  		t.Fatal(err)
   548  	}
   549  
   550  	if _, ok := abi.Methods["balance"]; !ok {
   551  		t.Error("expected 'balance' to be present")
   552  	}
   553  }
   554  
   555  func TestBareEvents(t *testing.T) {
   556  	const definition = `[
   557  	{ "type" : "event", "name" : "balance" },
   558  	{ "type" : "event", "name" : "anon", "anonymous" : true},
   559  	{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] },
   560  	{ "type" : "event", "name" : "tuple", "inputs" : [{ "indexed":false, "name":"t", "type":"tuple", "components":[{"name":"a", "type":"uint256"}] }, { "indexed":true, "name":"arg1", "type":"address" }] }
   561  	]`
   562  
   563  	arg0, _ := NewType("uint256", "", nil)
   564  	arg1, _ := NewType("address", "", nil)
   565  	tuple, _ := NewType("tuple", "", []ArgumentMarshaling{{Name: "a", Type: "uint256"}})
   566  
   567  	expectedEvents := map[string]struct {
   568  		Anonymous bool
   569  		Args      []Argument
   570  	}{
   571  		"balance": {false, nil},
   572  		"anon":    {true, nil},
   573  		"args": {false, []Argument{
   574  			{Name: "arg0", Type: arg0, Indexed: false},
   575  			{Name: "arg1", Type: arg1, Indexed: true},
   576  		}},
   577  		"tuple": {false, []Argument{
   578  			{Name: "t", Type: tuple, Indexed: false},
   579  			{Name: "arg1", Type: arg1, Indexed: true},
   580  		}},
   581  	}
   582  
   583  	abi, err := JSON(strings.NewReader(definition))
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  
   588  	if len(abi.Events) != len(expectedEvents) {
   589  		t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events))
   590  	}
   591  
   592  	for name, exp := range expectedEvents {
   593  		got, ok := abi.Events[name]
   594  		if !ok {
   595  			t.Errorf("could not found event %s", name)
   596  			continue
   597  		}
   598  		if got.Anonymous != exp.Anonymous {
   599  			t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous)
   600  		}
   601  		if len(got.Inputs) != len(exp.Args) {
   602  			t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs))
   603  			continue
   604  		}
   605  		for i, arg := range exp.Args {
   606  			if arg.Name != got.Inputs[i].Name {
   607  				t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name)
   608  			}
   609  			if arg.Indexed != got.Inputs[i].Indexed {
   610  				t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed)
   611  			}
   612  			if arg.Type.T != got.Inputs[i].Type.T {
   613  				t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T)
   614  			}
   615  		}
   616  	}
   617  }
   618  
   619  func TestUnpackEvent(t *testing.T) {
   620  	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"}]`
   621  	abi, err := JSON(strings.NewReader(abiJSON))
   622  	if err != nil {
   623  		t.Fatal(err)
   624  	}
   625  
   626  	const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
   627  	data, err := hex.DecodeString(hexdata)
   628  	if err != nil {
   629  		t.Fatal(err)
   630  	}
   631  	if len(data)%32 == 0 {
   632  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   633  	}
   634  
   635  	type ReceivedEvent struct {
   636  		Sender common.Address
   637  		Amount *big.Int
   638  		Memo   []byte
   639  	}
   640  	var ev ReceivedEvent
   641  
   642  	err = abi.Unpack(&ev, "received", data)
   643  	if err != nil {
   644  		t.Error(err)
   645  	}
   646  
   647  	type ReceivedAddrEvent struct {
   648  		Sender common.Address
   649  	}
   650  	var receivedAddrEv ReceivedAddrEvent
   651  	err = abi.Unpack(&receivedAddrEv, "receivedAddr", data)
   652  	if err != nil {
   653  		t.Error(err)
   654  	}
   655  }
   656  
   657  func TestUnpackEventIntoMap(t *testing.T) {
   658  	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"}]`
   659  	abi, err := JSON(strings.NewReader(abiJSON))
   660  	if err != nil {
   661  		t.Fatal(err)
   662  	}
   663  
   664  	const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
   665  	data, err := hex.DecodeString(hexdata)
   666  	if err != nil {
   667  		t.Fatal(err)
   668  	}
   669  	if len(data)%32 == 0 {
   670  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   671  	}
   672  
   673  	receivedMap := map[string]interface{}{}
   674  	expectedReceivedMap := map[string]interface{}{
   675  		"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
   676  		"amount": big.NewInt(1),
   677  		"memo":   []byte{88},
   678  	}
   679  	if err := abi.UnpackIntoMap(receivedMap, "received", data); err != nil {
   680  		t.Error(err)
   681  	}
   682  	if len(receivedMap) != 3 {
   683  		t.Error("unpacked `received` map expected to have length 3")
   684  	}
   685  	if receivedMap["sender"] != expectedReceivedMap["sender"] {
   686  		t.Error("unpacked `received` map does not match expected map")
   687  	}
   688  	if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
   689  		t.Error("unpacked `received` map does not match expected map")
   690  	}
   691  	if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
   692  		t.Error("unpacked `received` map does not match expected map")
   693  	}
   694  
   695  	receivedAddrMap := map[string]interface{}{}
   696  	if err = abi.UnpackIntoMap(receivedAddrMap, "receivedAddr", data); err != nil {
   697  		t.Error(err)
   698  	}
   699  	if len(receivedAddrMap) != 1 {
   700  		t.Error("unpacked `receivedAddr` map expected to have length 1")
   701  	}
   702  	if receivedAddrMap["sender"] != expectedReceivedMap["sender"] {
   703  		t.Error("unpacked `receivedAddr` map does not match expected map")
   704  	}
   705  }
   706  
   707  func TestUnpackMethodIntoMap(t *testing.T) {
   708  	const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
   709  	abi, err := JSON(strings.NewReader(abiJSON))
   710  	if err != nil {
   711  		t.Fatal(err)
   712  	}
   713  	const hexdata = `00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000158000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001580000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000015800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000158`
   714  	data, err := hex.DecodeString(hexdata)
   715  	if err != nil {
   716  		t.Fatal(err)
   717  	}
   718  	if len(data)%32 != 0 {
   719  		t.Errorf("len(data) is %d, want a multiple of 32", len(data))
   720  	}
   721  
   722  	receiveMap := map[string]interface{}{}
   723  	if err = abi.UnpackIntoMap(receiveMap, "receive", data); err != nil {
   724  		t.Error(err)
   725  	}
   726  	if len(receiveMap) > 0 {
   727  		t.Error("unpacked `receive` map expected to have length 0")
   728  	}
   729  
   730  	sendMap := map[string]interface{}{}
   731  	if err = abi.UnpackIntoMap(sendMap, "send", data); err != nil {
   732  		t.Error(err)
   733  	}
   734  	if len(sendMap) != 1 {
   735  		t.Error("unpacked `send` map expected to have length 1")
   736  	}
   737  	if sendMap["amount"].(*big.Int).Cmp(big.NewInt(1)) != 0 {
   738  		t.Error("unpacked `send` map expected `amount` value of 1")
   739  	}
   740  
   741  	getMap := map[string]interface{}{}
   742  	if err = abi.UnpackIntoMap(getMap, "get", data); err != nil {
   743  		t.Error(err)
   744  	}
   745  	if len(getMap) != 1 {
   746  		t.Error("unpacked `get` map expected to have length 1")
   747  	}
   748  	expectedBytes := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 88, 0}
   749  	if !bytes.Equal(getMap["hash"].([]byte), expectedBytes) {
   750  		t.Errorf("unpacked `get` map expected `hash` value of %v", expectedBytes)
   751  	}
   752  }
   753  
   754  func TestUnpackIntoMapNamingConflict(t *testing.T) {
   755  
   756  	var abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"get","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"send","outputs":[{"name":"amount","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"addr","type":"address"}],"name":"get","outputs":[{"name":"hash","type":"bytes"}],"payable":true,"stateMutability":"payable","type":"function"}]`
   757  	abi, err := JSON(strings.NewReader(abiJSON))
   758  	if err != nil {
   759  		t.Fatal(err)
   760  	}
   761  	var hexdata = `00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
   762  	data, err := hex.DecodeString(hexdata)
   763  	if err != nil {
   764  		t.Fatal(err)
   765  	}
   766  	if len(data)%32 == 0 {
   767  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   768  	}
   769  	getMap := map[string]interface{}{}
   770  	if err = abi.UnpackIntoMap(getMap, "get", data); err == nil {
   771  		t.Error("naming conflict between two methods; error expected")
   772  	}
   773  
   774  	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":"received","type":"event"}]`
   775  	abi, err = JSON(strings.NewReader(abiJSON))
   776  	if err != nil {
   777  		t.Fatal(err)
   778  	}
   779  	hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
   780  	data, err = hex.DecodeString(hexdata)
   781  	if err != nil {
   782  		t.Fatal(err)
   783  	}
   784  	if len(data)%32 == 0 {
   785  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   786  	}
   787  	receivedMap := map[string]interface{}{}
   788  	if err = abi.UnpackIntoMap(receivedMap, "received", data); err != nil {
   789  		t.Error("naming conflict between two events; no error expected")
   790  	}
   791  
   792  	abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"received","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"}]`
   793  	abi, err = JSON(strings.NewReader(abiJSON))
   794  	if err != nil {
   795  		t.Fatal(err)
   796  	}
   797  	if len(data)%32 == 0 {
   798  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   799  	}
   800  	if err = abi.UnpackIntoMap(receivedMap, "received", data); err == nil {
   801  		t.Error("naming conflict between an event and a method; error expected")
   802  	}
   803  
   804  	abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"received","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"}]`
   805  	abi, err = JSON(strings.NewReader(abiJSON))
   806  	if err != nil {
   807  		t.Fatal(err)
   808  	}
   809  	if len(data)%32 == 0 {
   810  		t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
   811  	}
   812  	expectedReceivedMap := map[string]interface{}{
   813  		"sender": common.HexToAddress("0x376c47978271565f56DEB45495afa69E59c16Ab2"),
   814  		"amount": big.NewInt(1),
   815  		"memo":   []byte{88},
   816  	}
   817  	if err = abi.UnpackIntoMap(receivedMap, "Received", data); err != nil {
   818  		t.Error(err)
   819  	}
   820  	if len(receivedMap) != 3 {
   821  		t.Error("unpacked `received` map expected to have length 3")
   822  	}
   823  	if receivedMap["sender"] != expectedReceivedMap["sender"] {
   824  		t.Error("unpacked `received` map does not match expected map")
   825  	}
   826  	if receivedMap["amount"].(*big.Int).Cmp(expectedReceivedMap["amount"].(*big.Int)) != 0 {
   827  		t.Error("unpacked `received` map does not match expected map")
   828  	}
   829  	if !bytes.Equal(receivedMap["memo"].([]byte), expectedReceivedMap["memo"].([]byte)) {
   830  		t.Error("unpacked `received` map does not match expected map")
   831  	}
   832  }
   833  
   834  func TestABI_MethodById(t *testing.T) {
   835  	const abiJSON = `[
   836  		{"type":"function","name":"receive","constant":false,"inputs":[{"name":"memo","type":"bytes"}],"outputs":[],"payable":true,"stateMutability":"payable"},
   837  		{"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"}]},
   838  		{"type":"function","name":"fixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"}]},
   839  		{"type":"function","name":"fixedArrBytes","constant":true,"inputs":[{"name":"str","type":"bytes"},{"name":"fixedArr","type":"uint256[2]"}]},
   840  		{"type":"function","name":"mixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr","type":"uint256[2]"},{"name":"dynArr","type":"uint256[]"}]},
   841  		{"type":"function","name":"doubleFixedArrStr","constant":true,"inputs":[{"name":"str","type":"string"},{"name":"fixedArr1","type":"uint256[2]"},{"name":"fixedArr2","type":"uint256[3]"}]},
   842  		{"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]"}]},
   843  		{"type":"function","name":"balance","constant":true},
   844  		{"type":"function","name":"send","constant":false,"inputs":[{"name":"amount","type":"uint256"}]},
   845  		{"type":"function","name":"test","constant":false,"inputs":[{"name":"number","type":"uint32"}]},
   846  		{"type":"function","name":"string","constant":false,"inputs":[{"name":"inputs","type":"string"}]},
   847  		{"type":"function","name":"bool","constant":false,"inputs":[{"name":"inputs","type":"bool"}]},
   848  		{"type":"function","name":"address","constant":false,"inputs":[{"name":"inputs","type":"address"}]},
   849  		{"type":"function","name":"uint64[2]","constant":false,"inputs":[{"name":"inputs","type":"uint64[2]"}]},
   850  		{"type":"function","name":"uint64[]","constant":false,"inputs":[{"name":"inputs","type":"uint64[]"}]},
   851  		{"type":"function","name":"foo","constant":false,"inputs":[{"name":"inputs","type":"uint32"}]},
   852  		{"type":"function","name":"bar","constant":false,"inputs":[{"name":"inputs","type":"uint32"},{"name":"string","type":"uint16"}]},
   853  		{"type":"function","name":"_slice","constant":false,"inputs":[{"name":"inputs","type":"uint32[2]"}]},
   854  		{"type":"function","name":"__slice256","constant":false,"inputs":[{"name":"inputs","type":"uint256[2]"}]},
   855  		{"type":"function","name":"sliceAddress","constant":false,"inputs":[{"name":"inputs","type":"address[]"}]},
   856  		{"type":"function","name":"sliceMultiAddress","constant":false,"inputs":[{"name":"a","type":"address[]"},{"name":"b","type":"address[]"}]}
   857  	]
   858  `
   859  	abi, err := JSON(strings.NewReader(abiJSON))
   860  	if err != nil {
   861  		t.Fatal(err)
   862  	}
   863  	for name, m := range abi.Methods {
   864  		a := fmt.Sprintf("%v", m)
   865  		m2, err := abi.MethodById(m.ID())
   866  		if err != nil {
   867  			t.Fatalf("Failed to look up ABI method: %v", err)
   868  		}
   869  		b := fmt.Sprintf("%v", m2)
   870  		if a != b {
   871  			t.Errorf("Method %v (id %x) not 'findable' by id in ABI", name, m.ID())
   872  		}
   873  	}
   874  
   875  	if _, err := abi.MethodById([]byte{0x00}); err == nil {
   876  		t.Errorf("Expected error, too short to decode data")
   877  	}
   878  	if _, err := abi.MethodById([]byte{}); err == nil {
   879  		t.Errorf("Expected error, too short to decode data")
   880  	}
   881  	if _, err := abi.MethodById(nil); err == nil {
   882  		t.Errorf("Expected error, nil is short to decode data")
   883  	}
   884  }
   885  
   886  func TestABI_EventById(t *testing.T) {
   887  	tests := []struct {
   888  		name  string
   889  		json  string
   890  		event string
   891  	}{
   892  		{
   893  			name: "",
   894  			json: `[
   895  			{"type":"event","name":"received","anonymous":false,"inputs":[
   896  				{"indexed":false,"name":"sender","type":"address"},
   897  				{"indexed":false,"name":"amount","type":"uint256"},
   898  				{"indexed":false,"name":"memo","type":"bytes"}
   899  				]
   900  			}]`,
   901  			event: "received(address,uint256,bytes)",
   902  		}, {
   903  			name: "",
   904  			json: `[
   905  				{ "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" },
   906  				{ "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" },
   907  				{ "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" },
   908  				{ "constant": false, "inputs": [ { "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transferFrom", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" },
   909  				{ "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint8" } ], "payable": false, "stateMutability": "view", "type": "function" },
   910  				{ "constant": true, "inputs": [ { "name": "_owner", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" },
   911  				{ "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" },
   912  				{ "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transfer", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" },
   913  				{ "constant": true, "inputs": [ { "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" },
   914  				{ "payable": true, "stateMutability": "payable", "type": "fallback" },
   915  				{ "anonymous": false, "inputs": [ { "indexed": true, "name": "owner", "type": "address" }, { "indexed": true, "name": "spender", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" },
   916  				{ "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "address" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }
   917  			]`,
   918  			event: "Transfer(address,address,uint256)",
   919  		},
   920  	}
   921  
   922  	for testnum, test := range tests {
   923  		abi, err := JSON(strings.NewReader(test.json))
   924  		if err != nil {
   925  			t.Error(err)
   926  		}
   927  
   928  		topic := test.event
   929  		topicID := crypto.Keccak256Hash([]byte(topic))
   930  
   931  		event, err := abi.EventByID(topicID)
   932  		if err != nil {
   933  			t.Fatalf("Failed to look up ABI method: %v, test #%d", err, testnum)
   934  		}
   935  		if event == nil {
   936  			t.Errorf("We should find a event for topic %s, test #%d", topicID.Hex(), testnum)
   937  		}
   938  
   939  		if event.ID() != topicID {
   940  			t.Errorf("Event id %s does not match topic %s, test #%d", event.ID().Hex(), topicID.Hex(), testnum)
   941  		}
   942  
   943  		unknowntopicID := crypto.Keccak256Hash([]byte("unknownEvent"))
   944  		unknownEvent, err := abi.EventByID(unknowntopicID)
   945  		if err == nil {
   946  			t.Errorf("EventByID should return an error if a topic is not found, test #%d", testnum)
   947  		}
   948  		if unknownEvent != nil {
   949  			t.Errorf("We should not find any event for topic %s, test #%d", unknowntopicID.Hex(), testnum)
   950  		}
   951  	}
   952  }
   953  
   954  func TestDuplicateMethodNames(t *testing.T) {
   955  	abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
   956  	contractAbi, err := JSON(strings.NewReader(abiJSON))
   957  	if err != nil {
   958  		t.Fatal(err)
   959  	}
   960  	if _, ok := contractAbi.Methods["transfer"]; !ok {
   961  		t.Fatalf("Could not find original method")
   962  	}
   963  	if _, ok := contractAbi.Methods["transfer0"]; !ok {
   964  		t.Fatalf("Could not find duplicate method")
   965  	}
   966  	if _, ok := contractAbi.Methods["transfer1"]; !ok {
   967  		t.Fatalf("Could not find duplicate method")
   968  	}
   969  	if _, ok := contractAbi.Methods["transfer2"]; ok {
   970  		t.Fatalf("Should not have found extra method")
   971  	}
   972  }
   973  
   974  func TestDoubleDuplicateMethodNames(t *testing.T) {
   975  	abiJSON := `[{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"}],"name":"transfer0","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"data","type":"bytes"},{"name":"customFallback","type":"string"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]`
   976  	contractAbi, err := JSON(strings.NewReader(abiJSON))
   977  	if err != nil {
   978  		t.Fatal(err)
   979  	}
   980  	if _, ok := contractAbi.Methods["transfer"]; !ok {
   981  		t.Fatalf("Could not find original method")
   982  	}
   983  	if _, ok := contractAbi.Methods["transfer0"]; !ok {
   984  		t.Fatalf("Could not find duplicate method")
   985  	}
   986  	if _, ok := contractAbi.Methods["transfer1"]; !ok {
   987  		t.Fatalf("Could not find duplicate method")
   988  	}
   989  	if _, ok := contractAbi.Methods["transfer2"]; ok {
   990  		t.Fatalf("Should not have found extra method")
   991  	}
   992  }