github.com/luckypickle/go-ethereum-vet@v1.14.2/signer/core/abihelper_test.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-ethereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package core 18 19 import ( 20 "fmt" 21 "strings" 22 "testing" 23 24 "io/ioutil" 25 "math/big" 26 "reflect" 27 28 "github.com/luckypickle/go-ethereum-vet/accounts/abi" 29 "github.com/luckypickle/go-ethereum-vet/common" 30 ) 31 32 func verify(t *testing.T, jsondata, calldata string, exp []interface{}) { 33 34 abispec, err := abi.JSON(strings.NewReader(jsondata)) 35 if err != nil { 36 t.Fatal(err) 37 } 38 cd := common.Hex2Bytes(calldata) 39 sigdata, argdata := cd[:4], cd[4:] 40 method, err := abispec.MethodById(sigdata) 41 42 if err != nil { 43 t.Fatal(err) 44 } 45 46 data, err := method.Inputs.UnpackValues(argdata) 47 48 if len(data) != len(exp) { 49 t.Fatalf("Mismatched length, expected %d, got %d", len(exp), len(data)) 50 } 51 for i, elem := range data { 52 if !reflect.DeepEqual(elem, exp[i]) { 53 t.Fatalf("Unpack error, arg %d, got %v, want %v", i, elem, exp[i]) 54 } 55 } 56 } 57 func TestNewUnpacker(t *testing.T) { 58 type unpackTest struct { 59 jsondata string 60 calldata string 61 exp []interface{} 62 } 63 testcases := []unpackTest{ 64 { // https://solidity.readthedocs.io/en/develop/abi-spec.html#use-of-dynamic-types 65 `[{"type":"function","name":"f", "inputs":[{"type":"uint256"},{"type":"uint32[]"},{"type":"bytes10"},{"type":"bytes"}]}]`, 66 // 0x123, [0x456, 0x789], "1234567890", "Hello, world!" 67 "8be65246" + "00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000", 68 []interface{}{ 69 big.NewInt(0x123), 70 []uint32{0x456, 0x789}, 71 [10]byte{49, 50, 51, 52, 53, 54, 55, 56, 57, 48}, 72 common.Hex2Bytes("48656c6c6f2c20776f726c6421"), 73 }, 74 }, { // https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#examples 75 `[{"type":"function","name":"sam","inputs":[{"type":"bytes"},{"type":"bool"},{"type":"uint256[]"}]}]`, 76 // "dave", true and [1,2,3] 77 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 78 []interface{}{ 79 []byte{0x64, 0x61, 0x76, 0x65}, 80 true, 81 []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}, 82 }, 83 }, { 84 `[{"type":"function","name":"send","inputs":[{"type":"uint256"}]}]`, 85 "a52c101e0000000000000000000000000000000000000000000000000000000000000012", 86 []interface{}{big.NewInt(0x12)}, 87 }, { 88 `[{"type":"function","name":"compareAndApprove","inputs":[{"type":"address"},{"type":"uint256"},{"type":"uint256"}]}]`, 89 "751e107900000000000000000000000000000133700000deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", 90 []interface{}{ 91 common.HexToAddress("0x00000133700000deadbeef000000000000000000"), 92 new(big.Int).SetBytes([]byte{0x00}), 93 big.NewInt(0x1), 94 }, 95 }, 96 } 97 for _, c := range testcases { 98 verify(t, c.jsondata, c.calldata, c.exp) 99 } 100 101 } 102 103 /* 104 func TestReflect(t *testing.T) { 105 a := big.NewInt(0) 106 b := new(big.Int).SetBytes([]byte{0x00}) 107 if !reflect.DeepEqual(a, b) { 108 t.Fatalf("Nope, %v != %v", a, b) 109 } 110 } 111 */ 112 113 func TestCalldataDecoding(t *testing.T) { 114 115 // send(uint256) : a52c101e 116 // compareAndApprove(address,uint256,uint256) : 751e1079 117 // issue(address[],uint256) : 42958b54 118 jsondata := ` 119 [ 120 {"type":"function","name":"send","inputs":[{"name":"a","type":"uint256"}]}, 121 {"type":"function","name":"compareAndApprove","inputs":[{"name":"a","type":"address"},{"name":"a","type":"uint256"},{"name":"a","type":"uint256"}]}, 122 {"type":"function","name":"issue","inputs":[{"name":"a","type":"address[]"},{"name":"a","type":"uint256"}]}, 123 {"type":"function","name":"sam","inputs":[{"name":"a","type":"bytes"},{"name":"a","type":"bool"},{"name":"a","type":"uint256[]"}]} 124 ]` 125 //Expected failures 126 for _, hexdata := range []string{ 127 "a52c101e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 128 "a52c101e000000000000000000000000000000000000000000000000000000000000001200", 129 "a52c101e00000000000000000000000000000000000000000000000000000000000000", 130 "a52c101e", 131 "a52c10", 132 "", 133 // Too short 134 "751e10790000000000000000000000000000000000000000000000000000000000000012", 135 "751e1079FFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 136 //Not valid multiple of 32 137 "deadbeef00000000000000000000000000000000000000000000000000000000000000", 138 //Too short 'issue' 139 "42958b5400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 140 // Too short compareAndApprove 141 "a52c101e00ff0000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 142 // From https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI 143 // contains a bool with illegal values 144 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 145 } { 146 _, err := parseCallData(common.Hex2Bytes(hexdata), jsondata) 147 if err == nil { 148 t.Errorf("Expected decoding to fail: %s", hexdata) 149 } 150 } 151 152 //Expected success 153 for _, hexdata := range []string{ 154 // From https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI 155 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 156 "a52c101e0000000000000000000000000000000000000000000000000000000000000012", 157 "a52c101eFFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 158 "751e1079000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 159 "42958b54" + 160 // start of dynamic type 161 "0000000000000000000000000000000000000000000000000000000000000040" + 162 //uint256 163 "0000000000000000000000000000000000000000000000000000000000000001" + 164 // length of array 165 "0000000000000000000000000000000000000000000000000000000000000002" + 166 // array values 167 "000000000000000000000000000000000000000000000000000000000000dead" + 168 "000000000000000000000000000000000000000000000000000000000000beef", 169 } { 170 _, err := parseCallData(common.Hex2Bytes(hexdata), jsondata) 171 if err != nil { 172 t.Errorf("Unexpected failure on input %s:\n %v (%d bytes) ", hexdata, err, len(common.Hex2Bytes(hexdata))) 173 } 174 } 175 } 176 177 func TestSelectorUnmarshalling(t *testing.T) { 178 var ( 179 db *AbiDb 180 err error 181 abistring []byte 182 abistruct abi.ABI 183 ) 184 185 db, err = NewAbiDBFromFile("../../cmd/clef/4byte.json") 186 if err != nil { 187 t.Fatal(err) 188 } 189 fmt.Printf("DB size %v\n", db.Size()) 190 for id, selector := range db.db { 191 192 abistring, err = MethodSelectorToAbi(selector) 193 if err != nil { 194 t.Error(err) 195 return 196 } 197 abistruct, err = abi.JSON(strings.NewReader(string(abistring))) 198 if err != nil { 199 t.Error(err) 200 return 201 } 202 m, err := abistruct.MethodById(common.Hex2Bytes(id[2:])) 203 if err != nil { 204 t.Error(err) 205 return 206 } 207 if m.Sig() != selector { 208 t.Errorf("Expected equality: %v != %v", m.Sig(), selector) 209 } 210 } 211 212 } 213 214 func TestCustomABI(t *testing.T) { 215 d, err := ioutil.TempDir("", "signer-4byte-test") 216 if err != nil { 217 t.Fatal(err) 218 } 219 filename := fmt.Sprintf("%s/4byte_custom.json", d) 220 abidb, err := NewAbiDBFromFiles("../../cmd/clef/4byte.json", filename) 221 if err != nil { 222 t.Fatal(err) 223 } 224 // Now we'll remove all existing signatures 225 abidb.db = make(map[string]string) 226 calldata := common.Hex2Bytes("a52c101edeadbeef") 227 _, err = abidb.LookupMethodSelector(calldata) 228 if err == nil { 229 t.Fatalf("Should not find a match on empty db") 230 } 231 if err = abidb.AddSignature("send(uint256)", calldata); err != nil { 232 t.Fatalf("Failed to save file: %v", err) 233 } 234 _, err = abidb.LookupMethodSelector(calldata) 235 if err != nil { 236 t.Fatalf("Should find a match for abi signature, got: %v", err) 237 } 238 //Check that it wrote to file 239 abidb2, err := NewAbiDBFromFile(filename) 240 if err != nil { 241 t.Fatalf("Failed to create new abidb: %v", err) 242 } 243 _, err = abidb2.LookupMethodSelector(calldata) 244 if err != nil { 245 t.Fatalf("Save failed: should find a match for abi signature after loading from disk") 246 } 247 }