EthabiTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. <?php
  2. namespace Test\Unit;
  3. use InvalidArgumentException;
  4. use Test\TestCase;
  5. use Web3\Utils;
  6. use Web3\Contracts\Ethabi;
  7. use Web3\Contracts\Types\Address;
  8. use Web3\Contracts\Types\Boolean;
  9. use Web3\Contracts\Types\Bytes;
  10. use Web3\Contracts\Types\DynamicBytes;
  11. use Web3\Contracts\Types\Integer;
  12. use Web3\Contracts\Types\Str;
  13. use Web3\Contracts\Types\Uinteger;
  14. class EthabiTest extends TestCase
  15. {
  16. /**
  17. * abi
  18. *
  19. * @var \Web3\Contracts\Ethabi
  20. */
  21. protected $abi;
  22. /**
  23. * testJsonMethodString
  24. * from GameToken approve function
  25. *
  26. * @var string
  27. */
  28. protected $testJsonMethodString = '{
  29. "constant": false,
  30. "inputs": [
  31. {
  32. "name": "_spender",
  33. "type": "address"
  34. },
  35. {
  36. "name": "_value",
  37. "type": "uint256"
  38. }
  39. ],
  40. "name": "approve",
  41. "outputs": [
  42. {
  43. "name": "success",
  44. "type": "bool"
  45. }
  46. ],
  47. "payable": false,
  48. "stateMutability": "nonpayable",
  49. "type": "function",
  50. "test": {
  51. "name": "testObject"
  52. }
  53. }';
  54. /**
  55. * encodingTests
  56. * from web3 abi.encodeParameter.js test
  57. * and web3 eth.abi.encodeParameters test
  58. * and web3 eth.abi.encodeParameter test
  59. *
  60. * @param array
  61. */
  62. protected $encodingTests = [
  63. [
  64. 'params' => [['uint256','string'], ['2345675643', 'Hello!%']],
  65. 'result' => '0x000000000000000000000000000000000000000000000000000000008bd02b7b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000748656c6c6f212500000000000000000000000000000000000000000000000000'
  66. ], [
  67. 'params' => [['uint8[]','bytes32'], [['34','434'], '0x324567dfff']],
  68. 'result' => '0x0000000000000000000000000000000000000000000000000000000000000040324567dfff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000001b2'
  69. ], [
  70. 'params' => [['address','address','address', 'address'], ['0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1','','0x0', null]],
  71. 'result' => '0x00000000000000000000000090f8bf6a479f320ead074411a4b0e7944ea8c9c1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
  72. ], [
  73. 'params' => [['bool[2]', 'bool[3]'], [[true, false], [false, false, true]]],
  74. 'result' => '0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001'
  75. ], [
  76. 'params' => [['int'], [1]],
  77. 'result' => '0x0000000000000000000000000000000000000000000000000000000000000001'
  78. ], [
  79. 'params' => [['int'], [16]],
  80. 'result' => '0x0000000000000000000000000000000000000000000000000000000000000010'
  81. ], [
  82. 'params' => [['int'], [-1]],
  83. 'result' => '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
  84. ], [
  85. 'params' => [['int256'], [1]],
  86. 'result' => '0x0000000000000000000000000000000000000000000000000000000000000001'
  87. ], [
  88. 'params' => [['int256'], [16]],
  89. 'result' => '0x0000000000000000000000000000000000000000000000000000000000000010'
  90. ], [
  91. 'params' => [['int256'], [-1]],
  92. 'result' => '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
  93. ], [
  94. 'params' => [['int[]'], [[3]]],
  95. 'result' => '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003'
  96. ], [
  97. 'params' => [['int256[]'], [[3]]],
  98. 'result' => '0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003'
  99. ], [
  100. 'params' => [['int256[]'], [[1,2,3]]],
  101. 'result' => '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003'
  102. ], [
  103. 'params' => [['int[]','int[]'], [[1,2],[3,4]]],
  104. 'result' => '0x000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004'
  105. ]
  106. ];
  107. /**
  108. * decodingTests
  109. * from web3 abi.decodeParameter.js test
  110. * and web3 eth.abi.decodeParameters test
  111. * and web3 eth.abi.decodeParameter test
  112. *
  113. * @param array
  114. */
  115. protected $decodingTests = [
  116. [
  117. 'params' => [['uint256'], '0x0000000000000000000000000000000000000000000000000000000000000010'],
  118. 'result' => ['16']
  119. ], [
  120. 'params' => [['string'], '0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000848656c6c6f212521000000000000000000000000000000000000000000000000'],
  121. 'result' => ['Hello!%!']
  122. ], [
  123. 'params' => [['uint256','string'], '0x000000000000000000000000000000000000000000000000000000008bd02b7b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000748656c6c6f212500000000000000000000000000000000000000000000000000'],
  124. 'result' => ['2345675643', 'Hello!%']
  125. ], [
  126. 'params' => [['string'], '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'],
  127. 'result' => ['']
  128. ], [
  129. 'params' => [['int256'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  130. 'result' => ['0']
  131. ], [
  132. 'params' => [['uint256'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  133. 'result' => ['0']
  134. ], [
  135. 'params' => [['address'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  136. 'result' => ['0x0000000000000000000000000000000000000000']
  137. ], [
  138. 'params' => [['bool'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  139. 'result' => [false]
  140. ], [
  141. 'params' => [['bytes'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  142. 'result' => ['0']
  143. ], [
  144. 'params' => [['bytes32'], '0x0000000000000000000000000000000000000000000000000000000000000000'],
  145. 'result' => ['0']
  146. ], [
  147. 'params' => [['bytes32'], '0xdf32340000000000000000000000000000000000000000000000000000000000'],
  148. 'result' => ['0xdf32340000000000000000000000000000000000000000000000000000000000']
  149. ], [
  150. 'params' => [['bytes32[]'], '0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002df32340000000000000000000000000000000000000000000000000000000000fdfd000000000000000000000000000000000000000000000000000000000000'],
  151. 'result' => ['0xdf32340000000000000000000000000000000000000000000000000000000000', '0xfdfd000000000000000000000000000000000000000000000000000000000000']
  152. ]
  153. ];
  154. /**
  155. * setUp
  156. *
  157. * @return void
  158. */
  159. public function setUp()
  160. {
  161. parent::setUp();
  162. // Error: Using $this when not in object context
  163. // $this->abi = new Ethabi([
  164. // 'address' => Address::class,
  165. // 'bool' => Boolean::class,
  166. // 'bytes' => Bytes::class,
  167. // 'int' => Integer::class,
  168. // 'string' => Str::class,
  169. // 'uint' => Uinteger::class,
  170. // ]);
  171. $this->abi = new Ethabi([
  172. 'address' => new Address,
  173. 'bool' => new Boolean,
  174. 'bytes' => new Bytes,
  175. 'dynamicBytes' => new DynamicBytes,
  176. 'int' => new Integer,
  177. 'string' => new Str,
  178. 'uint' => new Uinteger
  179. ]);
  180. }
  181. /**
  182. * testEncodeFunctionSignature
  183. *
  184. * @return void
  185. */
  186. public function testEncodeFunctionSignature()
  187. {
  188. $abi = $this->abi;
  189. $str = $abi->encodeFunctionSignature('baz(uint32,bool)');
  190. $this->assertEquals($str, '0xcdcd77c0');
  191. $json = json_decode($this->testJsonMethodString);
  192. $methodString = Utils::jsonMethodToString($json);
  193. $str = $abi->encodeFunctionSignature($methodString);
  194. $this->assertEquals($str, '0x095ea7b3');
  195. $str = $abi->encodeFunctionSignature('bar(bytes3[2])');
  196. $this->assertEquals($str, '0xfce353f6');
  197. $str = $abi->encodeFunctionSignature('sam(bytes,bool,uint256[])');
  198. $this->assertEquals($str, '0xa5643bf2');
  199. }
  200. /**
  201. * testEncodeEventSignature
  202. *
  203. * @return void
  204. */
  205. public function testEncodeEventSignature()
  206. {
  207. $abi = $this->abi;
  208. $str = $abi->encodeEventSignature('baz(uint32,bool)');
  209. $this->assertEquals($str, '0xcdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2');
  210. $json = json_decode($this->testJsonMethodString);
  211. $methodString = Utils::jsonMethodToString($json);
  212. $str = $abi->encodeEventSignature($methodString);
  213. $this->assertEquals($str, '0x095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba');
  214. }
  215. /**
  216. * testEncodeParameter
  217. *
  218. * @return void
  219. */
  220. public function testEncodeParameter()
  221. {
  222. $abi = $this->abi;
  223. $this->assertEquals('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', $abi->encodeParameter('int256', '-1'));
  224. }
  225. /**
  226. * testEncodeParameters
  227. *
  228. * @return void
  229. */
  230. public function testEncodeParameters()
  231. {
  232. $abi = $this->abi;
  233. foreach ($this->encodingTests as $test) {
  234. $this->assertEquals($test['result'], $abi->encodeParameters($test['params'][0], $test['params'][1]));
  235. }
  236. }
  237. /**
  238. * testDecodeParameter
  239. *
  240. * @return void
  241. */
  242. public function testDecodeParameter()
  243. {
  244. $abi = $this->abi;
  245. $this->assertEquals('16', $abi->decodeParameter('uint256', '0x0000000000000000000000000000000000000000000000000000000000000010')->toString());
  246. $this->assertEquals('16', $abi->decodeParameter('uint256', '0x0000000000000000000000000000000000000000000000000000000000000010')->toString());
  247. }
  248. /**
  249. * testDecodeParameters
  250. *
  251. * @return void
  252. */
  253. public function testDecodeParameters()
  254. {
  255. $abi = $this->abi;
  256. foreach ($this->decodingTests as $test) {
  257. $decoded = $abi->decodeParameters($test['params'][0], $test['params'][1]);
  258. foreach ($decoded as $key => $decoding) {
  259. if (!is_array($decoding)) {
  260. $this->assertEquals($test['result'][$key], $decoding);
  261. } else {
  262. foreach ($test['result'] as $rKey => $expected) {
  263. $this->assertEquals($expected, $decoding[$rKey]);
  264. }
  265. }
  266. }
  267. }
  268. }
  269. /**
  270. * testIssue71
  271. * test 33 bytes and 128 bytes string, see: https://github.com/sc0Vu/web3.php/issues/71
  272. * string generated from: https://www.lipsum.com/
  273. *
  274. * @return void
  275. */
  276. public function testIssue71()
  277. {
  278. $abi = $this->abi;
  279. $specialString = 'Lorem ipsum dolor sit amet metus.';
  280. $encodedString = $abi->encodeParameter('string', $specialString);
  281. $this->assertEquals($specialString, $abi->decodeParameter('string', $encodedString));
  282. $specialString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce pulvinar quam felis, suscipit posuere neque aliquam in cras amet.';
  283. $encodedString = $abi->encodeParameter('string', $specialString);
  284. $this->assertEquals($specialString, $abi->decodeParameter('string', $encodedString));
  285. }
  286. }