github.com/waltonchain/waltonchain_gwtc_src@v1.1.4-0.20201225072101-8a298c95a819/accounts/abi/abi_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-wtc library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-wtc library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package abi
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"log"
    23  	"math/big"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  
    28  	"github.com/wtc/go-wtc/common"
    29  	"github.com/wtc/go-wtc/crypto"
    30  )
    31  
    32  // formatSilceOutput add padding to the value and adds a size
    33  func formatSliceOutput(v ...[]byte) []byte {
    34  	off := common.LeftPadBytes(big.NewInt(int64(len(v))).Bytes(), 32)
    35  	output := append(off, make([]byte, 0, len(v)*32)...)
    36  
    37  	for _, value := range v {
    38  		output = append(output, common.LeftPadBytes(value, 32)...)
    39  	}
    40  	return output
    41  }
    42  
    43  // quick helper padding
    44  func pad(input []byte, size int, left bool) []byte {
    45  	if left {
    46  		return common.LeftPadBytes(input, size)
    47  	}
    48  	return common.RightPadBytes(input, size)
    49  }
    50  
    51  const jsondata = `
    52  [
    53  	{ "type" : "function", "name" : "balance", "constant" : true },
    54  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
    55  ]`
    56  
    57  const jsondata2 = `
    58  [
    59  	{ "type" : "function", "name" : "balance", "constant" : true },
    60  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
    61  	{ "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
    62  	{ "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
    63  	{ "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
    64  	{ "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
    65  	{ "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
    66  	{ "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
    67  	{ "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
    68  	{ "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
    69  	{ "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
    70  	{ "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
    71  	{ "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
    72  	{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
    73  ]`
    74  
    75  func TestReader(t *testing.T) {
    76  	Uint256, _ := NewType("uint256")
    77  	exp := ABI{
    78  		Methods: map[string]Method{
    79  			"balance": {
    80  				"balance", true, nil, nil,
    81  			},
    82  			"send": {
    83  				"send", false, []Argument{
    84  					{"amount", Uint256, false},
    85  				}, nil,
    86  			},
    87  		},
    88  	}
    89  
    90  	abi, err := JSON(strings.NewReader(jsondata))
    91  	if err != nil {
    92  		t.Error(err)
    93  	}
    94  
    95  	// deep equal fails for some reason
    96  	t.Skip()
    97  	if !reflect.DeepEqual(abi, exp) {
    98  		t.Errorf("\nabi: %v\ndoes not match exp: %v", abi, exp)
    99  	}
   100  }
   101  
   102  func TestTestNumbers(t *testing.T) {
   103  	abi, err := JSON(strings.NewReader(jsondata2))
   104  	if err != nil {
   105  		t.Error(err)
   106  		t.FailNow()
   107  	}
   108  
   109  	if _, err := abi.Pack("balance"); err != nil {
   110  		t.Error(err)
   111  	}
   112  
   113  	if _, err := abi.Pack("balance", 1); err == nil {
   114  		t.Error("expected error for balance(1)")
   115  	}
   116  
   117  	if _, err := abi.Pack("doesntexist", nil); err == nil {
   118  		t.Errorf("doesntexist shouldn't exist")
   119  	}
   120  
   121  	if _, err := abi.Pack("doesntexist", 1); err == nil {
   122  		t.Errorf("doesntexist(1) shouldn't exist")
   123  	}
   124  
   125  	if _, err := abi.Pack("send", big.NewInt(1000)); err != nil {
   126  		t.Error(err)
   127  	}
   128  
   129  	i := new(int)
   130  	*i = 1000
   131  	if _, err := abi.Pack("send", i); err == nil {
   132  		t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int")
   133  	}
   134  
   135  	if _, err := abi.Pack("test", uint32(1000)); err != nil {
   136  		t.Error(err)
   137  	}
   138  }
   139  
   140  func TestTestString(t *testing.T) {
   141  	abi, err := JSON(strings.NewReader(jsondata2))
   142  	if err != nil {
   143  		t.Error(err)
   144  		t.FailNow()
   145  	}
   146  
   147  	if _, err := abi.Pack("string", "hello world"); err != nil {
   148  		t.Error(err)
   149  	}
   150  }
   151  
   152  func TestTestBool(t *testing.T) {
   153  	abi, err := JSON(strings.NewReader(jsondata2))
   154  	if err != nil {
   155  		t.Error(err)
   156  		t.FailNow()
   157  	}
   158  
   159  	if _, err := abi.Pack("bool", true); err != nil {
   160  		t.Error(err)
   161  	}
   162  }
   163  
   164  func TestTestSlice(t *testing.T) {
   165  	abi, err := JSON(strings.NewReader(jsondata2))
   166  	if err != nil {
   167  		t.Error(err)
   168  		t.FailNow()
   169  	}
   170  
   171  	slice := make([]uint64, 2)
   172  	if _, err := abi.Pack("uint64[2]", slice); err != nil {
   173  		t.Error(err)
   174  	}
   175  
   176  	if _, err := abi.Pack("uint64[]", slice); err != nil {
   177  		t.Error(err)
   178  	}
   179  }
   180  
   181  func TestMethodSignature(t *testing.T) {
   182  	String, _ := NewType("string")
   183  	m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
   184  	exp := "foo(string,string)"
   185  	if m.Sig() != exp {
   186  		t.Error("signature mismatch", exp, "!=", m.Sig())
   187  	}
   188  
   189  	idexp := crypto.Keccak256([]byte(exp))[:4]
   190  	if !bytes.Equal(m.Id(), idexp) {
   191  		t.Errorf("expected ids to match %x != %x", m.Id(), idexp)
   192  	}
   193  
   194  	uintt, _ := NewType("uint")
   195  	m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
   196  	exp = "foo(uint256)"
   197  	if m.Sig() != exp {
   198  		t.Error("signature mismatch", exp, "!=", m.Sig())
   199  	}
   200  }
   201  
   202  func TestMultiPack(t *testing.T) {
   203  	abi, err := JSON(strings.NewReader(jsondata2))
   204  	if err != nil {
   205  		t.Error(err)
   206  		t.FailNow()
   207  	}
   208  
   209  	sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4]
   210  	sig = append(sig, make([]byte, 64)...)
   211  	sig[35] = 10
   212  	sig[67] = 11
   213  
   214  	packed, err := abi.Pack("bar", uint32(10), uint16(11))
   215  	if err != nil {
   216  		t.Error(err)
   217  		t.FailNow()
   218  	}
   219  
   220  	if !bytes.Equal(packed, sig) {
   221  		t.Errorf("expected %x got %x", sig, packed)
   222  	}
   223  }
   224  
   225  func ExampleJSON() {
   226  	const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
   227  
   228  	abi, err := JSON(strings.NewReader(definition))
   229  	if err != nil {
   230  		log.Fatalln(err)
   231  	}
   232  	out, err := abi.Pack("isBar", common.HexToAddress("01"))
   233  	if err != nil {
   234  		log.Fatalln(err)
   235  	}
   236  
   237  	fmt.Printf("%x\n", out)
   238  	// Output:
   239  	// 1f2c40920000000000000000000000000000000000000000000000000000000000000001
   240  }
   241  
   242  func TestInputVariableInputLength(t *testing.T) {
   243  	const definition = `[
   244  	{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
   245  	{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
   246  	{ "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
   247  	]`
   248  
   249  	abi, err := JSON(strings.NewReader(definition))
   250  	if err != nil {
   251  		t.Fatal(err)
   252  	}
   253  
   254  	// test one string
   255  	strin := "hello world"
   256  	strpack, err := abi.Pack("strOne", strin)
   257  	if err != nil {
   258  		t.Error(err)
   259  	}
   260  
   261  	offset := make([]byte, 32)
   262  	offset[31] = 32
   263  	length := make([]byte, 32)
   264  	length[31] = byte(len(strin))
   265  	value := common.RightPadBytes([]byte(strin), 32)
   266  	exp := append(offset, append(length, value...)...)
   267  
   268  	// ignore first 4 bytes of the output. This is the function identifier
   269  	strpack = strpack[4:]
   270  	if !bytes.Equal(strpack, exp) {
   271  		t.Errorf("expected %x, got %x\n", exp, strpack)
   272  	}
   273  
   274  	// test one bytes
   275  	btspack, err := abi.Pack("bytesOne", []byte(strin))
   276  	if err != nil {
   277  		t.Error(err)
   278  	}
   279  	// ignore first 4 bytes of the output. This is the function identifier
   280  	btspack = btspack[4:]
   281  	if !bytes.Equal(btspack, exp) {
   282  		t.Errorf("expected %x, got %x\n", exp, btspack)
   283  	}
   284  
   285  	//  test two strings
   286  	str1 := "hello"
   287  	str2 := "world"
   288  	str2pack, err := abi.Pack("strTwo", str1, str2)
   289  	if err != nil {
   290  		t.Error(err)
   291  	}
   292  
   293  	offset1 := make([]byte, 32)
   294  	offset1[31] = 64
   295  	length1 := make([]byte, 32)
   296  	length1[31] = byte(len(str1))
   297  	value1 := common.RightPadBytes([]byte(str1), 32)
   298  
   299  	offset2 := make([]byte, 32)
   300  	offset2[31] = 128
   301  	length2 := make([]byte, 32)
   302  	length2[31] = byte(len(str2))
   303  	value2 := common.RightPadBytes([]byte(str2), 32)
   304  
   305  	exp2 := append(offset1, offset2...)
   306  	exp2 = append(exp2, append(length1, value1...)...)
   307  	exp2 = append(exp2, append(length2, value2...)...)
   308  
   309  	// ignore first 4 bytes of the output. This is the function identifier
   310  	str2pack = str2pack[4:]
   311  	if !bytes.Equal(str2pack, exp2) {
   312  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   313  	}
   314  
   315  	// test two strings, first > 32, second < 32
   316  	str1 = strings.Repeat("a", 33)
   317  	str2pack, err = abi.Pack("strTwo", str1, str2)
   318  	if err != nil {
   319  		t.Error(err)
   320  	}
   321  
   322  	offset1 = make([]byte, 32)
   323  	offset1[31] = 64
   324  	length1 = make([]byte, 32)
   325  	length1[31] = byte(len(str1))
   326  	value1 = common.RightPadBytes([]byte(str1), 64)
   327  	offset2[31] = 160
   328  
   329  	exp2 = append(offset1, offset2...)
   330  	exp2 = append(exp2, append(length1, value1...)...)
   331  	exp2 = append(exp2, append(length2, value2...)...)
   332  
   333  	// ignore first 4 bytes of the output. This is the function identifier
   334  	str2pack = str2pack[4:]
   335  	if !bytes.Equal(str2pack, exp2) {
   336  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   337  	}
   338  
   339  	// test two strings, first > 32, second >32
   340  	str1 = strings.Repeat("a", 33)
   341  	str2 = strings.Repeat("a", 33)
   342  	str2pack, err = abi.Pack("strTwo", str1, str2)
   343  	if err != nil {
   344  		t.Error(err)
   345  	}
   346  
   347  	offset1 = make([]byte, 32)
   348  	offset1[31] = 64
   349  	length1 = make([]byte, 32)
   350  	length1[31] = byte(len(str1))
   351  	value1 = common.RightPadBytes([]byte(str1), 64)
   352  
   353  	offset2 = make([]byte, 32)
   354  	offset2[31] = 160
   355  	length2 = make([]byte, 32)
   356  	length2[31] = byte(len(str2))
   357  	value2 = common.RightPadBytes([]byte(str2), 64)
   358  
   359  	exp2 = append(offset1, offset2...)
   360  	exp2 = append(exp2, append(length1, value1...)...)
   361  	exp2 = append(exp2, append(length2, value2...)...)
   362  
   363  	// ignore first 4 bytes of the output. This is the function identifier
   364  	str2pack = str2pack[4:]
   365  	if !bytes.Equal(str2pack, exp2) {
   366  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   367  	}
   368  }
   369  
   370  func TestDefaultFunctionParsing(t *testing.T) {
   371  	const definition = `[{ "name" : "balance" }]`
   372  
   373  	abi, err := JSON(strings.NewReader(definition))
   374  	if err != nil {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	if _, ok := abi.Methods["balance"]; !ok {
   379  		t.Error("expected 'balance' to be present")
   380  	}
   381  }
   382  
   383  func TestBareEvents(t *testing.T) {
   384  	const definition = `[
   385  	{ "type" : "event", "name" : "balance" },
   386  	{ "type" : "event", "name" : "anon", "anonymous" : true},
   387  	{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }
   388  	]`
   389  
   390  	arg0, _ := NewType("uint256")
   391  	arg1, _ := NewType("address")
   392  
   393  	expectedEvents := map[string]struct {
   394  		Anonymous bool
   395  		Args      []Argument
   396  	}{
   397  		"balance": {false, nil},
   398  		"anon":    {true, nil},
   399  		"args": {false, []Argument{
   400  			{Name: "arg0", Type: arg0, Indexed: false},
   401  			{Name: "arg1", Type: arg1, Indexed: true},
   402  		}},
   403  	}
   404  
   405  	abi, err := JSON(strings.NewReader(definition))
   406  	if err != nil {
   407  		t.Fatal(err)
   408  	}
   409  
   410  	if len(abi.Events) != len(expectedEvents) {
   411  		t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events))
   412  	}
   413  
   414  	for name, exp := range expectedEvents {
   415  		got, ok := abi.Events[name]
   416  		if !ok {
   417  			t.Errorf("could not found event %s", name)
   418  			continue
   419  		}
   420  		if got.Anonymous != exp.Anonymous {
   421  			t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous)
   422  		}
   423  		if len(got.Inputs) != len(exp.Args) {
   424  			t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs))
   425  			continue
   426  		}
   427  		for i, arg := range exp.Args {
   428  			if arg.Name != got.Inputs[i].Name {
   429  				t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name)
   430  			}
   431  			if arg.Indexed != got.Inputs[i].Indexed {
   432  				t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed)
   433  			}
   434  			if arg.Type.T != got.Inputs[i].Type.T {
   435  				t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T)
   436  			}
   437  		}
   438  	}
   439  }