abihelper_test.go 11 KB

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