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 }