decred.org/dcrdex@v1.0.5/dex/networks/eth/abi_test.go (about) 1 // Copyright 2019 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum 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-ethereum 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 // This file lifted from go-ethereum/signer/fourbyte at v1.10.6 commit 18 // 576681f29b895dd39e559b7ba17fcd89b42e4833 and modified to make parseCalldata take 19 // an abi instead of a string. 20 package eth 21 22 import ( 23 "math/big" 24 "reflect" 25 "strings" 26 "testing" 27 28 "github.com/ethereum/go-ethereum/accounts/abi" 29 "github.com/ethereum/go-ethereum/common" 30 ) 31 32 func verify(t *testing.T, jsondata, calldata string, exp []any) { 33 abispec, err := abi.JSON(strings.NewReader(jsondata)) 34 if err != nil { 35 t.Fatal(err) 36 } 37 cd := common.Hex2Bytes(calldata) 38 sigdata, argdata := cd[:4], cd[4:] 39 method, err := abispec.MethodById(sigdata) 40 if err != nil { 41 t.Fatal(err) 42 } 43 data, err := method.Inputs.UnpackValues(argdata) 44 if err != nil { 45 t.Fatal(err) 46 } 47 if len(data) != len(exp) { 48 t.Fatalf("Mismatched length, expected %d, got %d", len(exp), len(data)) 49 } 50 for i, elem := range data { 51 if !reflect.DeepEqual(elem, exp[i]) { 52 t.Fatalf("Unpack error, arg %d, got %v, want %v", i, elem, exp[i]) 53 } 54 } 55 } 56 57 func TestNewUnpacker(t *testing.T) { 58 type unpackTest struct { 59 jsondata string 60 calldata string 61 exp []any 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 []any{ 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://docs.soliditylang.org/en/develop/abi-spec.html#examples 75 `[{"type":"function","name":"sam","inputs":[{"type":"bytes"},{"type":"bool"},{"type":"uint256[]"}]}]`, 76 // "dave", true and [1,2,3] 77 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 78 []any{ 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 []any{big.NewInt(0x12)}, 87 }, { 88 `[{"type":"function","name":"compareAndApprove","inputs":[{"type":"address"},{"type":"uint256"},{"type":"uint256"}]}]`, 89 "751e107900000000000000000000000000000133700000deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", 90 []any{ 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 func TestCalldataDecoding(t *testing.T) { 103 // send(uint256) : a52c101e 104 // compareAndApprove(address,uint256,uint256) : 751e1079 105 // issue(address[],uint256) : 42958b54 106 jsondata := ` 107 [ 108 {"type":"function","name":"send","inputs":[{"name":"a","type":"uint256"}]}, 109 {"type":"function","name":"compareAndApprove","inputs":[{"name":"a","type":"address"},{"name":"a","type":"uint256"},{"name":"a","type":"uint256"}]}, 110 {"type":"function","name":"issue","inputs":[{"name":"a","type":"address[]"},{"name":"a","type":"uint256"}]}, 111 {"type":"function","name":"sam","inputs":[{"name":"a","type":"bytes"},{"name":"a","type":"bool"},{"name":"a","type":"uint256[]"}]} 112 ]` 113 // Expected failures 114 for i, hexdata := range []string{ 115 "a52c101e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 116 "a52c101e000000000000000000000000000000000000000000000000000000000000001200", 117 "a52c101e00000000000000000000000000000000000000000000000000000000000000", 118 "a52c101e", 119 "a52c10", 120 "", 121 // Too short 122 "751e10790000000000000000000000000000000000000000000000000000000000000012", 123 "751e1079FFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 124 // Not valid multiple of 32 125 "deadbeef00000000000000000000000000000000000000000000000000000000000000", 126 // Too short 'issue' 127 "42958b5400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 128 // Too short compareAndApprove 129 "a52c101e00ff0000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042", 130 // From https://docs.soliditylang.org/en/develop/abi-spec.html 131 // contains a bool with illegal values 132 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 133 } { 134 abi, err := abi.JSON(strings.NewReader(jsondata)) 135 if err != nil { 136 t.Errorf("test %d: failed to parse abi: %v", i, err) 137 } 138 _, err = ParseCallData(common.Hex2Bytes(hexdata), &abi) 139 if err == nil { 140 t.Errorf("test %d: expected decoding to fail: %s", i, hexdata) 141 } 142 } 143 // Expected success 144 for i, hexdata := range []string{ 145 // From https://docs.soliditylang.org/en/develop/abi-spec.html 146 "a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", 147 "a52c101e0000000000000000000000000000000000000000000000000000000000000012", 148 "a52c101eFFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 149 "751e1079000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 150 "42958b54" + 151 // start of dynamic type 152 "0000000000000000000000000000000000000000000000000000000000000040" + 153 // uint256 154 "0000000000000000000000000000000000000000000000000000000000000001" + 155 // length of array 156 "0000000000000000000000000000000000000000000000000000000000000002" + 157 // array values 158 "000000000000000000000000000000000000000000000000000000000000dead" + 159 "000000000000000000000000000000000000000000000000000000000000beef", 160 } { 161 abi, err := abi.JSON(strings.NewReader(jsondata)) 162 if err != nil { 163 t.Errorf("test %d: failed to parse abi: %v", i, err) 164 } 165 _, err = ParseCallData(common.Hex2Bytes(hexdata), &abi) 166 if err != nil { 167 t.Errorf("test %d: unexpected failure on input %s:\n %v (%d bytes) ", i, hexdata, err, len(common.Hex2Bytes(hexdata))) 168 } 169 } 170 } 171 172 func TestMaliciousABIStrings(t *testing.T) { 173 tests := []string{ 174 "func(uint256,uint256,[]uint256)", 175 "func(uint256,uint256,uint256,)", 176 "func(,uint256,uint256,uint256)", 177 } 178 data := common.Hex2Bytes("4401a6e40000000000000000000000000000000000000000000000000000000000000012") 179 for i, tt := range tests { 180 _, err := verifySelector(tt, data) 181 if err == nil { 182 t.Errorf("test %d: expected error for selector '%v'", i, tt) 183 } 184 } 185 }