github.com/Elemental-core/elementalcore@v0.0.0-20191206075037-63891242267a/accounts/abi/abi_test.go (about)

     1  // Copyright 2015 The elementalcore Authors
     2  // This file is part of the elementalcore library.
     3  //
     4  // The elementalcore 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 elementalcore 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 elementalcore 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/Elemental-core/elementalcore/common"
    29  	"github.com/Elemental-core/elementalcore/crypto"
    30  )
    31  
    32  const jsondata = `
    33  [
    34  	{ "type" : "function", "name" : "balance", "constant" : true },
    35  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] }
    36  ]`
    37  
    38  const jsondata2 = `
    39  [
    40  	{ "type" : "function", "name" : "balance", "constant" : true },
    41  	{ "type" : "function", "name" : "send", "constant" : false, "inputs" : [ { "name" : "amount", "type" : "uint256" } ] },
    42  	{ "type" : "function", "name" : "test", "constant" : false, "inputs" : [ { "name" : "number", "type" : "uint32" } ] },
    43  	{ "type" : "function", "name" : "string", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "string" } ] },
    44  	{ "type" : "function", "name" : "bool", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "bool" } ] },
    45  	{ "type" : "function", "name" : "address", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address" } ] },
    46  	{ "type" : "function", "name" : "uint64[2]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[2]" } ] },
    47  	{ "type" : "function", "name" : "uint64[]", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint64[]" } ] },
    48  	{ "type" : "function", "name" : "foo", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" } ] },
    49  	{ "type" : "function", "name" : "bar", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32" }, { "name" : "string", "type" : "uint16" } ] },
    50  	{ "type" : "function", "name" : "slice", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint32[2]" } ] },
    51  	{ "type" : "function", "name" : "slice256", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "uint256[2]" } ] },
    52  	{ "type" : "function", "name" : "sliceAddress", "constant" : false, "inputs" : [ { "name" : "inputs", "type" : "address[]" } ] },
    53  	{ "type" : "function", "name" : "sliceMultiAddress", "constant" : false, "inputs" : [ { "name" : "a", "type" : "address[]" }, { "name" : "b", "type" : "address[]" } ] }
    54  ]`
    55  
    56  func TestReader(t *testing.T) {
    57  	Uint256, _ := NewType("uint256")
    58  	exp := ABI{
    59  		Methods: map[string]Method{
    60  			"balance": {
    61  				"balance", true, nil, nil,
    62  			},
    63  			"send": {
    64  				"send", false, []Argument{
    65  					{"amount", Uint256, false},
    66  				}, nil,
    67  			},
    68  		},
    69  	}
    70  
    71  	abi, err := JSON(strings.NewReader(jsondata))
    72  	if err != nil {
    73  		t.Error(err)
    74  	}
    75  
    76  	// deep equal fails for some reason
    77  	t.Skip()
    78  	if !reflect.DeepEqual(abi, exp) {
    79  		t.Errorf("\nabi: %v\ndoes not match exp: %v", abi, exp)
    80  	}
    81  }
    82  
    83  func TestTestNumbers(t *testing.T) {
    84  	abi, err := JSON(strings.NewReader(jsondata2))
    85  	if err != nil {
    86  		t.Error(err)
    87  		t.FailNow()
    88  	}
    89  
    90  	if _, err := abi.Pack("balance"); err != nil {
    91  		t.Error(err)
    92  	}
    93  
    94  	if _, err := abi.Pack("balance", 1); err == nil {
    95  		t.Error("expected error for balance(1)")
    96  	}
    97  
    98  	if _, err := abi.Pack("doesntexist", nil); err == nil {
    99  		t.Errorf("doesntexist shouldn't exist")
   100  	}
   101  
   102  	if _, err := abi.Pack("doesntexist", 1); err == nil {
   103  		t.Errorf("doesntexist(1) shouldn't exist")
   104  	}
   105  
   106  	if _, err := abi.Pack("send", big.NewInt(1000)); err != nil {
   107  		t.Error(err)
   108  	}
   109  
   110  	i := new(int)
   111  	*i = 1000
   112  	if _, err := abi.Pack("send", i); err == nil {
   113  		t.Errorf("expected send( ptr ) to throw, requires *big.Int instead of *int")
   114  	}
   115  
   116  	if _, err := abi.Pack("test", uint32(1000)); err != nil {
   117  		t.Error(err)
   118  	}
   119  }
   120  
   121  func TestTestString(t *testing.T) {
   122  	abi, err := JSON(strings.NewReader(jsondata2))
   123  	if err != nil {
   124  		t.Error(err)
   125  		t.FailNow()
   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.Error(err)
   137  		t.FailNow()
   138  	}
   139  
   140  	if _, err := abi.Pack("bool", true); err != nil {
   141  		t.Error(err)
   142  	}
   143  }
   144  
   145  func TestTestSlice(t *testing.T) {
   146  	abi, err := JSON(strings.NewReader(jsondata2))
   147  	if err != nil {
   148  		t.Error(err)
   149  		t.FailNow()
   150  	}
   151  
   152  	slice := make([]uint64, 2)
   153  	if _, err := abi.Pack("uint64[2]", slice); err != nil {
   154  		t.Error(err)
   155  	}
   156  
   157  	if _, err := abi.Pack("uint64[]", slice); err != nil {
   158  		t.Error(err)
   159  	}
   160  }
   161  
   162  func TestMethodSignature(t *testing.T) {
   163  	String, _ := NewType("string")
   164  	m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
   165  	exp := "foo(string,string)"
   166  	if m.Sig() != exp {
   167  		t.Error("signature mismatch", exp, "!=", m.Sig())
   168  	}
   169  
   170  	idexp := crypto.Keccak256([]byte(exp))[:4]
   171  	if !bytes.Equal(m.Id(), idexp) {
   172  		t.Errorf("expected ids to match %x != %x", m.Id(), idexp)
   173  	}
   174  
   175  	uintt, _ := NewType("uint256")
   176  	m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
   177  	exp = "foo(uint256)"
   178  	if m.Sig() != exp {
   179  		t.Error("signature mismatch", exp, "!=", m.Sig())
   180  	}
   181  }
   182  
   183  func TestMultiPack(t *testing.T) {
   184  	abi, err := JSON(strings.NewReader(jsondata2))
   185  	if err != nil {
   186  		t.Error(err)
   187  		t.FailNow()
   188  	}
   189  
   190  	sig := crypto.Keccak256([]byte("bar(uint32,uint16)"))[:4]
   191  	sig = append(sig, make([]byte, 64)...)
   192  	sig[35] = 10
   193  	sig[67] = 11
   194  
   195  	packed, err := abi.Pack("bar", uint32(10), uint16(11))
   196  	if err != nil {
   197  		t.Error(err)
   198  		t.FailNow()
   199  	}
   200  
   201  	if !bytes.Equal(packed, sig) {
   202  		t.Errorf("expected %x got %x", sig, packed)
   203  	}
   204  }
   205  
   206  func ExampleJSON() {
   207  	const definition = `[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"isBar","outputs":[{"name":"","type":"bool"}],"type":"function"}]`
   208  
   209  	abi, err := JSON(strings.NewReader(definition))
   210  	if err != nil {
   211  		log.Fatalln(err)
   212  	}
   213  	out, err := abi.Pack("isBar", common.HexToAddress("01"))
   214  	if err != nil {
   215  		log.Fatalln(err)
   216  	}
   217  
   218  	fmt.Printf("%x\n", out)
   219  	// Output:
   220  	// 1f2c40920000000000000000000000000000000000000000000000000000000000000001
   221  }
   222  
   223  func TestInputVariableInputLength(t *testing.T) {
   224  	const definition = `[
   225  	{ "type" : "function", "name" : "strOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" } ] },
   226  	{ "type" : "function", "name" : "bytesOne", "constant" : true, "inputs" : [ { "name" : "str", "type" : "bytes" } ] },
   227  	{ "type" : "function", "name" : "strTwo", "constant" : true, "inputs" : [ { "name" : "str", "type" : "string" }, { "name" : "str1", "type" : "string" } ] }
   228  	]`
   229  
   230  	abi, err := JSON(strings.NewReader(definition))
   231  	if err != nil {
   232  		t.Fatal(err)
   233  	}
   234  
   235  	// test one string
   236  	strin := "hello world"
   237  	strpack, err := abi.Pack("strOne", strin)
   238  	if err != nil {
   239  		t.Error(err)
   240  	}
   241  
   242  	offset := make([]byte, 32)
   243  	offset[31] = 32
   244  	length := make([]byte, 32)
   245  	length[31] = byte(len(strin))
   246  	value := common.RightPadBytes([]byte(strin), 32)
   247  	exp := append(offset, append(length, value...)...)
   248  
   249  	// ignore first 4 bytes of the output. This is the function identifier
   250  	strpack = strpack[4:]
   251  	if !bytes.Equal(strpack, exp) {
   252  		t.Errorf("expected %x, got %x\n", exp, strpack)
   253  	}
   254  
   255  	// test one bytes
   256  	btspack, err := abi.Pack("bytesOne", []byte(strin))
   257  	if err != nil {
   258  		t.Error(err)
   259  	}
   260  	// ignore first 4 bytes of the output. This is the function identifier
   261  	btspack = btspack[4:]
   262  	if !bytes.Equal(btspack, exp) {
   263  		t.Errorf("expected %x, got %x\n", exp, btspack)
   264  	}
   265  
   266  	//  test two strings
   267  	str1 := "hello"
   268  	str2 := "world"
   269  	str2pack, err := abi.Pack("strTwo", str1, str2)
   270  	if err != nil {
   271  		t.Error(err)
   272  	}
   273  
   274  	offset1 := make([]byte, 32)
   275  	offset1[31] = 64
   276  	length1 := make([]byte, 32)
   277  	length1[31] = byte(len(str1))
   278  	value1 := common.RightPadBytes([]byte(str1), 32)
   279  
   280  	offset2 := make([]byte, 32)
   281  	offset2[31] = 128
   282  	length2 := make([]byte, 32)
   283  	length2[31] = byte(len(str2))
   284  	value2 := common.RightPadBytes([]byte(str2), 32)
   285  
   286  	exp2 := append(offset1, offset2...)
   287  	exp2 = append(exp2, append(length1, value1...)...)
   288  	exp2 = append(exp2, append(length2, value2...)...)
   289  
   290  	// ignore first 4 bytes of the output. This is the function identifier
   291  	str2pack = str2pack[4:]
   292  	if !bytes.Equal(str2pack, exp2) {
   293  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   294  	}
   295  
   296  	// test two strings, first > 32, second < 32
   297  	str1 = strings.Repeat("a", 33)
   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), 64)
   308  	offset2[31] = 160
   309  
   310  	exp2 = append(offset1, offset2...)
   311  	exp2 = append(exp2, append(length1, value1...)...)
   312  	exp2 = append(exp2, append(length2, value2...)...)
   313  
   314  	// ignore first 4 bytes of the output. This is the function identifier
   315  	str2pack = str2pack[4:]
   316  	if !bytes.Equal(str2pack, exp2) {
   317  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   318  	}
   319  
   320  	// test two strings, first > 32, second >32
   321  	str1 = strings.Repeat("a", 33)
   322  	str2 = strings.Repeat("a", 33)
   323  	str2pack, err = abi.Pack("strTwo", str1, str2)
   324  	if err != nil {
   325  		t.Error(err)
   326  	}
   327  
   328  	offset1 = make([]byte, 32)
   329  	offset1[31] = 64
   330  	length1 = make([]byte, 32)
   331  	length1[31] = byte(len(str1))
   332  	value1 = common.RightPadBytes([]byte(str1), 64)
   333  
   334  	offset2 = make([]byte, 32)
   335  	offset2[31] = 160
   336  	length2 = make([]byte, 32)
   337  	length2[31] = byte(len(str2))
   338  	value2 = common.RightPadBytes([]byte(str2), 64)
   339  
   340  	exp2 = append(offset1, offset2...)
   341  	exp2 = append(exp2, append(length1, value1...)...)
   342  	exp2 = append(exp2, append(length2, value2...)...)
   343  
   344  	// ignore first 4 bytes of the output. This is the function identifier
   345  	str2pack = str2pack[4:]
   346  	if !bytes.Equal(str2pack, exp2) {
   347  		t.Errorf("expected %x, got %x\n", exp, str2pack)
   348  	}
   349  }
   350  
   351  func TestDefaultFunctionParsing(t *testing.T) {
   352  	const definition = `[{ "name" : "balance" }]`
   353  
   354  	abi, err := JSON(strings.NewReader(definition))
   355  	if err != nil {
   356  		t.Fatal(err)
   357  	}
   358  
   359  	if _, ok := abi.Methods["balance"]; !ok {
   360  		t.Error("expected 'balance' to be present")
   361  	}
   362  }
   363  
   364  func TestBareEvents(t *testing.T) {
   365  	const definition = `[
   366  	{ "type" : "event", "name" : "balance" },
   367  	{ "type" : "event", "name" : "anon", "anonymous" : true},
   368  	{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }
   369  	]`
   370  
   371  	arg0, _ := NewType("uint256")
   372  	arg1, _ := NewType("address")
   373  
   374  	expectedEvents := map[string]struct {
   375  		Anonymous bool
   376  		Args      []Argument
   377  	}{
   378  		"balance": {false, nil},
   379  		"anon":    {true, nil},
   380  		"args": {false, []Argument{
   381  			{Name: "arg0", Type: arg0, Indexed: false},
   382  			{Name: "arg1", Type: arg1, Indexed: true},
   383  		}},
   384  	}
   385  
   386  	abi, err := JSON(strings.NewReader(definition))
   387  	if err != nil {
   388  		t.Fatal(err)
   389  	}
   390  
   391  	if len(abi.Events) != len(expectedEvents) {
   392  		t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events))
   393  	}
   394  
   395  	for name, exp := range expectedEvents {
   396  		got, ok := abi.Events[name]
   397  		if !ok {
   398  			t.Errorf("could not found event %s", name)
   399  			continue
   400  		}
   401  		if got.Anonymous != exp.Anonymous {
   402  			t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous)
   403  		}
   404  		if len(got.Inputs) != len(exp.Args) {
   405  			t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs))
   406  			continue
   407  		}
   408  		for i, arg := range exp.Args {
   409  			if arg.Name != got.Inputs[i].Name {
   410  				t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name)
   411  			}
   412  			if arg.Indexed != got.Inputs[i].Indexed {
   413  				t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed)
   414  			}
   415  			if arg.Type.T != got.Inputs[i].Type.T {
   416  				t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T)
   417  			}
   418  		}
   419  	}
   420  }