functions.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. // SPDX-License-Identifier: Apache-2.0
  2. use parity_scale_codec::{Decode, Encode};
  3. use crate::{build_solidity, build_wasm, load_abi};
  4. #[test]
  5. fn constructors() {
  6. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  7. struct Val(u64);
  8. // parse
  9. let mut runtime = build_solidity(
  10. "
  11. contract test {
  12. uint64 result;
  13. constructor() public {
  14. result = 1;
  15. }
  16. function get() public returns (uint64) {
  17. return result;
  18. }
  19. }",
  20. );
  21. runtime.constructor(0, Vec::new());
  22. runtime.function("get", Vec::new());
  23. assert_eq!(runtime.output(), Val(1).encode());
  24. // parse
  25. let mut runtime = build_solidity(
  26. "
  27. contract test {
  28. uint64 result;
  29. constructor(uint64 x) public {
  30. result = x;
  31. }
  32. function get() public returns (uint64) {
  33. return result;
  34. }
  35. }",
  36. );
  37. runtime.constructor(0, Val(0xaa_bb_cc_dd).encode());
  38. runtime.function("get", Vec::new());
  39. assert_eq!(runtime.output(), Val(0xaa_bb_cc_dd).encode());
  40. }
  41. #[test]
  42. fn constructor_wrong_selector() {
  43. let mut runtime = build_solidity(
  44. "
  45. contract test {
  46. uint64 result;
  47. constructor(uint64 x) public {
  48. result = x;
  49. }
  50. function get() public returns (uint64) {
  51. return result;
  52. }
  53. }",
  54. );
  55. runtime.raw_constructor_failure(vec![0xaa, 0xbb, 0xcc, 0xdd]);
  56. runtime.function("get", Vec::new());
  57. }
  58. #[test]
  59. fn constructor_override_selector() {
  60. let mut runtime = build_solidity(
  61. r#"
  62. contract test {
  63. uint64 result;
  64. @selector([1, 2, 3, 4])
  65. constructor(uint64 x) {
  66. result = x;
  67. }
  68. function get() public returns (uint64) {
  69. return result;
  70. }
  71. }"#,
  72. );
  73. let mut input: Vec<u8> = vec![1, 2, 3, 4];
  74. input.extend(0xaa_bb_cc_ddu64.encode());
  75. runtime.raw_constructor(input);
  76. runtime.function("get", Vec::new());
  77. assert_eq!(runtime.output(), 0xaa_bb_cc_ddu64.encode());
  78. }
  79. #[test]
  80. fn function_override_selector() {
  81. let mut runtime = build_solidity(
  82. r#"
  83. contract test {
  84. uint64 result;
  85. constructor() {
  86. result = 1;
  87. }
  88. @selector([1, 2, 3, 4])
  89. function set(uint64 x) public {
  90. result = x;
  91. }
  92. function get() public returns (uint64) {
  93. return result;
  94. }
  95. }"#,
  96. );
  97. let mut input: Vec<u8> = vec![1, 2, 3, 4];
  98. input.extend(0xaa_bb_cc_ddu64.encode());
  99. runtime.raw_function(input);
  100. runtime.function("get", Vec::new());
  101. assert_eq!(runtime.output(), 0xaa_bb_cc_ddu64.encode());
  102. }
  103. #[test]
  104. fn fallback() {
  105. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  106. struct Val(u64);
  107. // parse
  108. let mut runtime = build_solidity(
  109. "
  110. contract test {
  111. int64 result = 102;
  112. function get() public returns (int64) {
  113. return result;
  114. }
  115. fallback() external {
  116. result = 356;
  117. }
  118. }",
  119. );
  120. runtime.raw_function([0xaa, 0xbb, 0xcc, 0xdd, 0xff].to_vec());
  121. runtime.function("get", Vec::new());
  122. assert_eq!(runtime.output(), Val(356).encode());
  123. }
  124. #[test]
  125. fn function_wrong_selector() {
  126. let mut runtime = build_solidity(
  127. "
  128. contract test {
  129. uint64 result;
  130. constructor(uint64 x) public {
  131. result = x;
  132. }
  133. function get() public returns (uint64) {
  134. return result;
  135. }
  136. }",
  137. );
  138. runtime.raw_function_failure(vec![0xaa, 0xbb, 0xcc, 0xdd]);
  139. }
  140. #[test]
  141. fn nofallback() {
  142. // parse
  143. let mut runtime = build_solidity(
  144. "
  145. contract test {
  146. int64 result = 102;
  147. function get() public returns (int64) {
  148. return result;
  149. }
  150. }",
  151. );
  152. runtime.constructor(0, vec![]);
  153. runtime.raw_function_failure([0xaa, 0xbb, 0xcc, 0xdd, 0xff].to_vec());
  154. runtime.function("get", Vec::new());
  155. assert_eq!(runtime.output(), 102i64.encode());
  156. }
  157. #[test]
  158. fn test_overloading() {
  159. // parse
  160. let mut runtime = build_solidity(
  161. "
  162. contract test {
  163. uint32 public result = 1;
  164. constructor() public {
  165. foo(true);
  166. assert(result == 102);
  167. foo(500);
  168. assert(result == 510);
  169. }
  170. function foo(bool x) private {
  171. if (x) {
  172. result = 102;
  173. }
  174. }
  175. function foo(uint32 x) private {
  176. result = x + 10;
  177. }
  178. }",
  179. );
  180. runtime.constructor(0, Vec::new());
  181. }
  182. #[test]
  183. fn shadowing() {
  184. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  185. struct Val(u64);
  186. let src = "
  187. contract test {
  188. uint64 result;
  189. function goodset(uint64 val) public {
  190. result = val;
  191. }
  192. function badset(uint64 val) public {
  193. uint64 result = val;
  194. }
  195. function get() public returns (uint64) {
  196. return result;
  197. }
  198. }";
  199. // parse
  200. let mut runtime = build_solidity(src);
  201. runtime.constructor(0, Vec::new());
  202. runtime.function("goodset", Val(0x1234_5678_9abc_def0).encode());
  203. runtime.function("get", Vec::new());
  204. assert_eq!(runtime.output(), Val(0x1234_5678_9abc_def0).encode());
  205. runtime.function("badset", Val(1).encode());
  206. runtime.function("get", Vec::new());
  207. assert_eq!(runtime.output(), Val(0x1234_5678_9abc_def0).encode());
  208. }
  209. #[test]
  210. fn test_loops() {
  211. // parse
  212. let mut runtime = build_solidity(
  213. "
  214. contract test {
  215. uint32 public result = 1;
  216. constructor() public {
  217. uint32 n = 0;
  218. for (uint32 i = 0; i < 1000; i += 100) {
  219. n += 1;
  220. }
  221. assert(n == 10);
  222. n = 0;
  223. for (uint32 i = 0; i < 1000; i += 100) {
  224. if (true)
  225. continue;
  226. n += 1;
  227. }
  228. assert(n == 0);
  229. n = 0;
  230. for (uint32 i = 0; i < 1000; i += 100) {
  231. n += 1;
  232. break;
  233. }
  234. assert(n == 1);
  235. n = 0;
  236. while (n < 10) {
  237. n += 9;
  238. }
  239. assert(n == 18);
  240. n = 0;
  241. while (false) {
  242. n += 1000;
  243. }
  244. assert(n == 0);
  245. do {
  246. n += 9;
  247. }
  248. while(false);
  249. assert(n == 9);
  250. }
  251. }",
  252. );
  253. runtime.constructor(0, Vec::new());
  254. }
  255. #[test]
  256. fn test_example() {
  257. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  258. struct Val32(i32);
  259. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  260. struct ValBool(bool);
  261. // parse
  262. let src = include_str!("../../examples/example.sol");
  263. let mut runtime = build_solidity(src);
  264. runtime.constructor(0, Val32(102).encode());
  265. runtime.function("is_zombie_reaper", Vec::new());
  266. assert_eq!(runtime.output(), ValBool(false).encode());
  267. runtime.function("reap_processes", Vec::new());
  268. runtime.function("run_queue", Vec::new());
  269. }
  270. #[test]
  271. fn test_large_vals() {
  272. // parse
  273. let src = "
  274. contract test {
  275. function large() public returns (int) {
  276. return 102;
  277. }
  278. function large2(int x) public returns (int) {
  279. return x + 100;
  280. }
  281. function doda() public {
  282. int x = large();
  283. assert(large2(10) == 110);
  284. }
  285. }";
  286. let mut runtime = build_solidity(src);
  287. runtime.constructor(0, Vec::new());
  288. runtime.function("doda", Vec::new());
  289. }
  290. #[test]
  291. fn args_and_returns() {
  292. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  293. struct Val32(i32);
  294. let mut runtime = build_solidity(
  295. "
  296. contract foobar {
  297. function foo1() public returns (int32 a) {
  298. a = -102;
  299. }
  300. function foo2() public returns (int32 a) {
  301. a = -102;
  302. return 553;
  303. }
  304. }",
  305. );
  306. runtime.function("foo1", Vec::new());
  307. assert_eq!(runtime.output(), Val32(-102).encode());
  308. runtime.function("foo2", Vec::new());
  309. assert_eq!(runtime.output(), Val32(553).encode());
  310. }
  311. #[test]
  312. fn named_argument_call() {
  313. let mut runtime = build_solidity(
  314. "
  315. contract foobar {
  316. function foo1(bool x) public returns (int32 a) {
  317. return 2;
  318. }
  319. function foo1(uint32 x) public returns (int32 a) {
  320. a = bar({});
  321. }
  322. function bar() private returns (int32) {
  323. return 1;
  324. }
  325. function test() public {
  326. assert(foo1({ x: true }) == 2);
  327. assert(foo1({ x: 102 }) == 1);
  328. }
  329. }",
  330. );
  331. runtime.function("test", Vec::new());
  332. }
  333. #[test]
  334. fn positional_argument_call() {
  335. let mut runtime = build_solidity(
  336. "
  337. contract foobar {
  338. function foo1(bool x) public returns (int32 a) {
  339. return 2;
  340. }
  341. function foo1(uint32 x) public returns (int32 a) {
  342. return 1;
  343. }
  344. function test() public {
  345. assert(foo1(true) == 2);
  346. assert(foo1(102) == 1);
  347. }
  348. }",
  349. );
  350. runtime.function("test", Vec::new());
  351. }
  352. #[test]
  353. fn print() {
  354. let mut runtime = build_solidity(
  355. r#"
  356. contract foobar {
  357. function test() public {
  358. print("Hello, world");
  359. }
  360. }"#,
  361. );
  362. runtime.function("test", Vec::new());
  363. }
  364. #[test]
  365. fn destructuring_call() {
  366. let mut runtime = build_solidity(
  367. r#"
  368. contract c {
  369. function func1() public returns (int32, bool) {
  370. return (102, true);
  371. }
  372. function test() public {
  373. (int32 a, bool b) = func1();
  374. assert(a == 102 && b == true);
  375. }
  376. }"#,
  377. );
  378. runtime.constructor(0, Vec::new());
  379. runtime.function("test", Vec::new());
  380. let mut runtime = build_solidity(
  381. r#"
  382. contract c {
  383. function func1(int32 x) public returns (int32, bool) {
  384. return (102 + x, true);
  385. }
  386. function test() public {
  387. (int32 a, bool b) = func1({x: 5});
  388. assert(a == 107 && b == true);
  389. }
  390. }"#,
  391. );
  392. runtime.constructor(0, Vec::new());
  393. runtime.function("test", Vec::new());
  394. let mut runtime = build_solidity(
  395. r#"
  396. contract c {
  397. function test() public {
  398. b x = new b();
  399. (int32 a, bool b) = x.func1({x: 5});
  400. assert(a == 107 && b == true);
  401. (a, b) = x.func1(-1);
  402. assert(a == 101 && b == true);
  403. }
  404. }
  405. contract b {
  406. function func1(int32 x) public returns (int32, bool) {
  407. return (102 + x, true);
  408. }
  409. }"#,
  410. );
  411. runtime.constructor(0, Vec::new());
  412. runtime.function("test", Vec::new());
  413. }
  414. #[test]
  415. fn global_functions() {
  416. let mut runtime = build_solidity(
  417. r#"
  418. function global_function() pure returns (uint32) {
  419. return 102;
  420. }
  421. contract c {
  422. function test() public {
  423. uint64 x = global_function();
  424. assert(x == 102);
  425. }
  426. }"#,
  427. );
  428. runtime.function("test", Vec::new());
  429. let mut runtime = build_solidity(
  430. r#"
  431. function global_function() pure returns (uint32) {
  432. return 102;
  433. }
  434. function global_function2() pure returns (uint32) {
  435. return global_function() + 5;
  436. }
  437. contract c {
  438. function test() public {
  439. uint64 x = global_function2();
  440. assert(x == 107);
  441. }
  442. }"#,
  443. );
  444. runtime.function("test", Vec::new());
  445. let mut runtime = build_solidity(
  446. r#"
  447. function global_function() pure returns (uint32) {
  448. return 102;
  449. }
  450. function global_function2() pure returns (uint32) {
  451. return global_function() + 5;
  452. }
  453. contract c {
  454. function test() public {
  455. function() internal returns (uint32) ftype = global_function2;
  456. uint64 x = ftype();
  457. assert(x == 107);
  458. }
  459. }"#,
  460. );
  461. runtime.function("test", Vec::new());
  462. }
  463. #[test]
  464. fn virtual_function_member_access() {
  465. let src = r##"
  466. interface IERC1155Receiver {
  467. @selector([1, 2, 3, 4])
  468. function onERC1155Received() external returns (bytes4);
  469. }
  470. abstract contract ERC1155 {
  471. function _doSafeTransferAcceptanceCheck() internal pure returns (bytes4) {
  472. return IERC1155Receiver.onERC1155Received.selector;
  473. }
  474. }
  475. contract C is ERC1155 {
  476. function create() public pure returns (bytes4) {
  477. return _doSafeTransferAcceptanceCheck();
  478. }
  479. }"##;
  480. // The create function is the only one appearing in the metadata.
  481. let abi = load_abi(&build_wasm(src, false)[0].1);
  482. let messages = abi.spec().messages();
  483. assert_eq!(messages.len(), 1);
  484. assert_eq!(messages[0].label(), "create");
  485. // The create function returns the selector of IERC1155Receiver.onERC1155Received
  486. let mut runtime = build_solidity(src);
  487. runtime.function("create", vec![]);
  488. assert_eq!(runtime.output(), vec![1, 2, 3, 4]);
  489. }