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 }