calls.rs 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::{build_solidity, build_solidity_with_options};
  3. use parity_scale_codec::{Decode, Encode};
  4. use primitive_types::U256;
  5. use solang::codegen::revert::{PanicCode, SolidityError};
  6. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  7. struct RevertReturn(u32, String);
  8. #[test]
  9. fn revert() {
  10. let mut runtime = build_solidity(
  11. r#"
  12. contract bar {
  13. function test() public {
  14. revert("yo!");
  15. }
  16. function a() public {
  17. b();
  18. }
  19. function b() public {
  20. c();
  21. }
  22. function c() public {
  23. d();
  24. }
  25. function d() public {
  26. revert("revert value has to be passed down the stack");
  27. }
  28. }"#,
  29. );
  30. runtime.function_expect_failure("test", Vec::new());
  31. assert_eq!(runtime.output().len(), 4 + "yo!".to_string().encode().len());
  32. runtime.function_expect_failure("a", Vec::new());
  33. let expected_error = (
  34. 0x08c379a0u32.to_be_bytes(), // "selector" of "Error(string)"
  35. "revert value has to be passed down the stack".to_string(),
  36. );
  37. assert_eq!(runtime.output(), expected_error.encode());
  38. let mut runtime = build_solidity(
  39. r##"
  40. contract c {
  41. function test() public {
  42. revert();
  43. }
  44. }"##,
  45. );
  46. runtime.function_expect_failure("test", Vec::new());
  47. assert_eq!(runtime.output().len(), 0);
  48. }
  49. #[test]
  50. fn require() {
  51. let msg = "Program testing can be used to show the presence of bugs, but never to show their absence!".to_string();
  52. let src = format!(
  53. r#"contract c {{
  54. function test1() public pure {{
  55. require(false, "{}");
  56. }}
  57. function test2() public pure {{
  58. require(true, "{}");
  59. }}
  60. }}"#,
  61. &msg, &msg
  62. );
  63. let mut runtime = build_solidity(&src);
  64. runtime.function_expect_failure("test1", Vec::new());
  65. let selector = 0x08c379a0u32.to_be_bytes();
  66. assert_eq!(runtime.output(), (selector, msg).encode());
  67. runtime.function("test2", Vec::new());
  68. assert_eq!(runtime.output().len(), 0);
  69. }
  70. #[test]
  71. fn input_wrong_size() {
  72. let mut runtime = build_solidity(
  73. r##"
  74. contract c {
  75. function test(int32 x) public {
  76. }
  77. }"##,
  78. );
  79. runtime.function_expect_failure("test", b"A".to_vec());
  80. // the decoder does check if there is too much data
  81. runtime.function_expect_failure("test", b"ABCDE".to_vec());
  82. }
  83. #[test]
  84. fn external_call_not_exist() {
  85. let mut runtime = build_solidity(
  86. r##"
  87. contract c {
  88. function test() public {
  89. other o = other(address(102));
  90. o.test();
  91. }
  92. }
  93. contract other {
  94. function test() public {
  95. }
  96. }"##,
  97. );
  98. runtime.function_expect_failure("test", Vec::new());
  99. }
  100. #[test]
  101. fn contract_already_exists() {
  102. let mut runtime = build_solidity(
  103. r##"
  104. contract c {
  105. function test() public {
  106. other o = new other{salt: 0}();
  107. other t = new other{salt: 0}();
  108. }
  109. }
  110. contract other {
  111. function test() public {
  112. }
  113. }"##,
  114. );
  115. runtime.constructor(0, Vec::new());
  116. runtime.function_expect_failure("test", Vec::new());
  117. let mut runtime = build_solidity(
  118. r##"
  119. contract c {
  120. function test() public {
  121. other o = new other();
  122. other t = new other();
  123. }
  124. }
  125. contract other {
  126. function test() public {
  127. }
  128. }"##,
  129. );
  130. runtime.constructor(0, Vec::new());
  131. runtime.function("test", Vec::new());
  132. }
  133. #[test]
  134. fn try_catch_external_calls() {
  135. let mut runtime = build_solidity(
  136. r##"
  137. contract c {
  138. function test() public {
  139. other o = new other();
  140. int32 x = 0;
  141. try o.test() returns (int32 y, bool) {
  142. x = y;
  143. } catch (bytes) {
  144. x = 2;
  145. }
  146. assert(x == 102);
  147. }
  148. }
  149. contract other {
  150. function test() public returns (int32, bool) {
  151. return (102, true);
  152. }
  153. }
  154. "##,
  155. );
  156. runtime.constructor(0, Vec::new());
  157. runtime.function("test", Vec::new());
  158. let mut runtime = build_solidity(
  159. r#"
  160. contract c {
  161. function test() public {
  162. other o = new other();
  163. int32 x = 0;
  164. try o.test() returns (int32 y, bool) {
  165. x = y;
  166. } catch (bytes c) {
  167. assert(c == hex"08c379a00c666f6f");
  168. x = 2;
  169. }
  170. assert(x == 2);
  171. }
  172. }
  173. contract other {
  174. function test() public returns (int32, bool) {
  175. revert("foo");
  176. }
  177. }
  178. "#,
  179. );
  180. runtime.constructor(0, Vec::new());
  181. runtime.function("test", Vec::new());
  182. let mut runtime = build_solidity(
  183. r#"
  184. contract c {
  185. function test() public {
  186. other o = new other();
  187. try o.test(1) {
  188. print("shouldn't be here");
  189. assert(false);
  190. } catch Error(string foo) {
  191. print(foo);
  192. assert(foo == "yes");
  193. } catch (bytes c) {
  194. print("shouldn't be here");
  195. assert(false);
  196. }
  197. try o.test(2) {
  198. print("shouldn't be here");
  199. assert(false);
  200. } catch Error(string foo) {
  201. print(foo);
  202. assert(foo == "no");
  203. } catch (bytes c) {
  204. print("shouldn't be here");
  205. assert(false);
  206. }
  207. try o.test(3) {
  208. print("shouldn't be here");
  209. assert(false);
  210. } catch Error(string foo) {
  211. print("shouldn't be here");
  212. assert(false);
  213. } catch (bytes c) {
  214. assert(c.length == 0);
  215. }
  216. }
  217. }
  218. contract other {
  219. function test(int x) public {
  220. if (x == 1) {
  221. revert("yes");
  222. } else if (x == 2) {
  223. revert("no");
  224. } else {
  225. revert();
  226. }
  227. }
  228. }
  229. "#,
  230. );
  231. runtime.constructor(0, Vec::new());
  232. runtime.function("test", Vec::new());
  233. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  234. struct Ret(u32);
  235. let mut runtime = build_solidity(
  236. r#"
  237. contract dominator {
  238. child c;
  239. function create_child() public {
  240. c = (new child)();
  241. }
  242. function call_child() public view returns (int64) {
  243. return c.get_a();
  244. }
  245. function test() public pure returns (int32) {
  246. try c.go_bang() returns (int32 l) {
  247. print("try call success");
  248. return 8000;
  249. }
  250. catch Error(string l) {
  251. print("try error path");
  252. print(l);
  253. return 4000;
  254. }
  255. catch {
  256. print("try catch path");
  257. return 2000;
  258. }
  259. }
  260. }
  261. contract child {
  262. int64 a;
  263. constructor() public {
  264. a = 102;
  265. }
  266. function get_a() public view returns (int64) {
  267. return a;
  268. }
  269. function set_a(int64 l) public {
  270. a = l;
  271. }
  272. function go_bang() public pure returns (int32) {
  273. revert("gone bang in child");
  274. }
  275. }"#,
  276. );
  277. runtime.constructor(0, Vec::new());
  278. runtime.function("create_child", Vec::new());
  279. runtime.function("test", Vec::new());
  280. assert_eq!(runtime.output(), 4000i32.encode());
  281. }
  282. #[test]
  283. fn try_catch_external_calls_dont_decode_returns() {
  284. // try not using the return values of test() - revert case
  285. // note the absense of "try o.test() returns (int32 y, bool) {"
  286. let mut runtime = build_solidity(
  287. r#"
  288. contract c {
  289. function test() public returns (int32 x) {
  290. other o = new other();
  291. try o.test() {
  292. x = 1;
  293. } catch (bytes c) {
  294. x = 2;
  295. }
  296. }
  297. }
  298. contract other {
  299. function test() public returns (int32, bool) {
  300. revert("foo");
  301. }
  302. }
  303. "#,
  304. );
  305. runtime.constructor(0, Vec::new());
  306. runtime.function("test", Vec::new());
  307. assert_eq!(runtime.output(), 2i32.encode());
  308. // try not using the return values of test() - normal case
  309. // note the absense of "try o.test() returns (int32 y, bool) {"
  310. let mut runtime = build_solidity(
  311. r##"
  312. contract c {
  313. function test() public returns (int32 x) {
  314. other o = new other();
  315. try o.test({meh: false}) {
  316. x = 1;
  317. } catch (bytes c) {
  318. x = 2;
  319. }
  320. }
  321. }
  322. contract other {
  323. function test(bool meh) public returns (int32, bool) {
  324. return (5, meh);
  325. }
  326. }
  327. "##,
  328. );
  329. runtime.constructor(0, Vec::new());
  330. runtime.function("test", Vec::new());
  331. assert_eq!(runtime.output(), 1i32.encode());
  332. }
  333. #[test]
  334. fn try_catch_constructor() {
  335. let mut runtime = build_solidity(
  336. r##"
  337. contract c {
  338. function test() public {
  339. int x;
  340. try (new other)() {
  341. x = 102;
  342. } catch (bytes) {
  343. x = 2;
  344. }
  345. assert(x == 102);
  346. }
  347. }
  348. contract other {
  349. function test() public returns (int32, bool) {
  350. return (102, true);
  351. }
  352. }
  353. "##,
  354. );
  355. runtime.constructor(0, Vec::new());
  356. runtime.function("test", Vec::new());
  357. let mut runtime = build_solidity(
  358. r##"
  359. contract c {
  360. function test() public {
  361. int x;
  362. try new other({foo: true}) returns (other o) {
  363. (x, bool yata) = o.test();
  364. } catch (bytes) {
  365. x = 2;
  366. }
  367. assert(x == 102);
  368. }
  369. }
  370. contract other {
  371. constructor(bool foo) public {
  372. //
  373. }
  374. function test() public returns (int32, bool) {
  375. return (102, true);
  376. }
  377. }
  378. "##,
  379. );
  380. runtime.constructor(0, Vec::new());
  381. runtime.function("test", Vec::new());
  382. let mut runtime = build_solidity(
  383. r#"
  384. contract c {
  385. function test() public {
  386. int32 x = 0;
  387. try new other(true) {
  388. x = 1;
  389. } catch (bytes c) {
  390. print("returns:{}".format(c));
  391. assert(c == hex"08c379a00c666f6f");
  392. x = 2;
  393. }
  394. assert(x == 2);
  395. }
  396. }
  397. contract other {
  398. constructor(bool foo) public {
  399. revert("foo");
  400. }
  401. function _ext() public {}
  402. }
  403. "#,
  404. );
  405. runtime.constructor(0, Vec::new());
  406. runtime.function("test", Vec::new());
  407. }
  408. #[test]
  409. fn local_destructure_call() {
  410. let mut runtime = build_solidity(
  411. r#"
  412. contract c {
  413. function test() public {
  414. (, bytes32 b, string s) = foo();
  415. assert(b == "0123");
  416. assert(s == "abcd");
  417. }
  418. function foo() public returns (bool, bytes32, string) {
  419. return (true, "0123", "abcd");
  420. }
  421. }
  422. "#,
  423. );
  424. runtime.function("test", Vec::new());
  425. }
  426. #[test]
  427. fn payable_constructors() {
  428. // no contructors means constructor is not payable
  429. let mut runtime = build_solidity(
  430. r##"
  431. contract c {
  432. function test(string a) public {}
  433. }"##,
  434. );
  435. runtime.set_transferred_value(1);
  436. runtime.raw_constructor_failure(runtime.contracts()[0].code.constructors[0].clone());
  437. assert!(runtime
  438. .debug_buffer()
  439. .contains("runtime_error: non payable constructor"));
  440. // contructors w/o payable means can't send value
  441. let mut runtime = build_solidity(
  442. r##"
  443. contract c {
  444. constructor() public {
  445. int32 a = 0;
  446. }
  447. function test(string a) public {}
  448. }"##,
  449. );
  450. runtime.set_transferred_value(1);
  451. runtime.raw_constructor_failure(runtime.contracts()[0].code.constructors[0].clone());
  452. assert!(runtime
  453. .debug_buffer()
  454. .contains("runtime_error: non payable constructor"));
  455. // contructors w/ payable means can send value
  456. let mut runtime = build_solidity(
  457. r##"
  458. contract c {
  459. constructor() public payable {
  460. int32 a = 0;
  461. }
  462. function test(string a) public {}
  463. }"##,
  464. );
  465. runtime.set_transferred_value(1);
  466. runtime.constructor(0, Vec::new());
  467. }
  468. #[test]
  469. fn payable_functions() {
  470. // function w/o payable means can't send value
  471. let mut runtime = build_solidity(
  472. r##"
  473. contract c {
  474. function test() public {
  475. }
  476. }"##,
  477. );
  478. runtime.constructor(0, Vec::new());
  479. runtime.set_transferred_value(1);
  480. runtime.function_expect_failure("test", Vec::new());
  481. // test both
  482. let mut runtime = build_solidity(
  483. r##"
  484. contract c {
  485. function test() payable public {
  486. }
  487. function test2() public {
  488. }
  489. }"##,
  490. );
  491. runtime.constructor(0, Vec::new());
  492. runtime.set_transferred_value(1);
  493. runtime.function_expect_failure("test2", Vec::new());
  494. runtime.set_transferred_value(1);
  495. runtime.function("test", Vec::new());
  496. // test fallback and receive
  497. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  498. struct Ret(u32);
  499. let mut runtime = build_solidity(
  500. r##"
  501. contract c {
  502. int32 x;
  503. function get_x() public returns (int32) {
  504. return x;
  505. }
  506. function test() payable public {
  507. x = 1;
  508. }
  509. fallback() external {
  510. x = 2;
  511. }
  512. receive() payable external {
  513. x = 3;
  514. }
  515. }"##,
  516. );
  517. runtime.constructor(0, Vec::new());
  518. runtime.set_transferred_value(1);
  519. runtime.raw_function(b"abde".to_vec());
  520. runtime.function("get_x", Vec::new());
  521. assert_eq!(runtime.output(), Ret(3).encode());
  522. runtime.raw_function(b"abde".to_vec());
  523. runtime.function("get_x", Vec::new());
  524. assert_eq!(runtime.output(), Ret(2).encode());
  525. let mut runtime = build_solidity(
  526. r##"
  527. contract c {
  528. int32 x;
  529. function get_x() public returns (int32) {
  530. return x;
  531. }
  532. function test() payable public {
  533. x = 1;
  534. }
  535. receive() payable external {
  536. x = 3;
  537. }
  538. }"##,
  539. );
  540. runtime.constructor(0, Vec::new());
  541. runtime.set_transferred_value(1);
  542. runtime.raw_function(b"abde".to_vec());
  543. runtime.function("get_x", Vec::new());
  544. assert_eq!(runtime.output(), Ret(3).encode());
  545. runtime.raw_function_failure(b"abde".to_vec());
  546. let mut runtime = build_solidity(
  547. r##"
  548. contract c {
  549. int32 x;
  550. function get_x() public returns (int32) {
  551. return x;
  552. }
  553. function test() payable public {
  554. x = 1;
  555. }
  556. fallback() external {
  557. x = 2;
  558. }
  559. }"##,
  560. );
  561. runtime.constructor(0, Vec::new());
  562. runtime.set_transferred_value(1);
  563. runtime.raw_function_failure(b"abde".to_vec());
  564. runtime.set_transferred_value(0);
  565. runtime.raw_function(b"abde".to_vec());
  566. runtime.function("get_x", Vec::new());
  567. assert_eq!(runtime.output(), Ret(2).encode());
  568. }
  569. #[test]
  570. fn hash_tests() {
  571. let mut runtime = build_solidity(
  572. r#"
  573. contract tester {
  574. function test() public {
  575. bytes32 hash = keccak256("Hello, World!");
  576. assert(hash == hex"acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f");
  577. }
  578. }"#,
  579. );
  580. runtime.function("test", Vec::new());
  581. let mut runtime = build_solidity(
  582. r#"
  583. contract tester {
  584. function test() public {
  585. bytes memory s = "Hello, World!";
  586. bytes32 hash = keccak256(s);
  587. assert(hash == hex"acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f");
  588. }
  589. }"#,
  590. );
  591. runtime.function("test", Vec::new());
  592. let mut runtime = build_solidity(
  593. r#"
  594. contract tester {
  595. bytes s = "Hello, World!";
  596. function test() public {
  597. bytes32 hash = keccak256(s);
  598. assert(hash == hex"acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f");
  599. }
  600. }"#,
  601. );
  602. runtime.constructor(0, Vec::new());
  603. runtime.function("test", Vec::new());
  604. let mut runtime = build_solidity(
  605. r#"
  606. contract tester {
  607. function test() public {
  608. bytes32 hash = sha256("Hello, World!");
  609. assert(hash == hex"dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f");
  610. }
  611. }"#,
  612. );
  613. runtime.function("test", Vec::new());
  614. let mut runtime = build_solidity(
  615. r#"
  616. contract tester {
  617. function test() public {
  618. bytes32 hash = blake2_256("Hello, World!");
  619. assert(hash == hex"511bc81dde11180838c562c82bb35f3223f46061ebde4a955c27b3f489cf1e03");
  620. }
  621. }"#,
  622. );
  623. runtime.function("test", Vec::new());
  624. let mut runtime = build_solidity(
  625. r#"
  626. contract tester {
  627. function test() public {
  628. bytes16 hash = blake2_128("Hello, World!");
  629. assert(hash == hex"3895c59e4aeb0903396b5be3fbec69fe");
  630. }
  631. }"#,
  632. );
  633. runtime.function("test", Vec::new());
  634. let mut runtime = build_solidity(
  635. r#"
  636. contract tester {
  637. function test() public {
  638. bytes20 hash = ripemd160("Hello, World!");
  639. assert(hash == hex"527a6a4b9a6da75607546842e0e00105350b1aaf");
  640. }
  641. }"#,
  642. );
  643. runtime.function("test", Vec::new());
  644. }
  645. #[test]
  646. fn try_catch_reachable() {
  647. // ensure that implicit return gets added correctly if catch reachable not
  648. let _ = build_solidity(
  649. r##"
  650. contract AddNumbers { function add(uint256 a, uint256 b) external returns (uint256 c) {c = a + b;} }
  651. contract Example {
  652. AddNumbers addContract;
  653. event StringFailure(string stringFailure);
  654. event BytesFailure(bytes bytesFailure);
  655. function exampleFunction(uint256 _a, uint256 _b) public returns (uint256 _c) {
  656. try addContract.add(_a, _b) returns (uint256 _value) {
  657. return (_value);
  658. } catch Error(string memory _err) {
  659. // This may occur if there is an overflow with the two numbers and the `AddNumbers` contract explicitly fails with a `revert()`
  660. emit StringFailure(_err);
  661. } catch (bytes memory _err) {
  662. emit BytesFailure(_err);
  663. }
  664. _c = 1;
  665. }
  666. }"##,
  667. );
  668. let _ = build_solidity(
  669. r##"
  670. contract AddNumbers { function add(uint256 a, uint256 b) external returns (uint256 c) {c = a + b;} }
  671. contract Example {
  672. AddNumbers addContract;
  673. event StringFailure(string stringFailure);
  674. event BytesFailure(bytes bytesFailure);
  675. function exampleFunction(uint256 _a, uint256 _b) public returns (uint256 _c) {
  676. try addContract.add(_a, _b) returns (uint256 _value) {
  677. return (_value);
  678. } catch Error(string memory _err) {
  679. // This may occur if there is an overflow with the two numbers and the `AddNumbers` contract explicitly fails with a `revert()`
  680. emit StringFailure(_err);
  681. } catch (bytes memory _err) {
  682. emit BytesFailure(_err);
  683. return;
  684. }
  685. _c = 1;
  686. }
  687. }"##,
  688. );
  689. }
  690. #[test]
  691. fn log_api_call_return_values_works() {
  692. let mut runtime = build_solidity_with_options(
  693. r#"
  694. contract Test {
  695. constructor () payable {}
  696. function test() public {
  697. try new Other() returns (Other o) {
  698. o.foo();
  699. }
  700. catch {}
  701. }
  702. }
  703. contract Other {
  704. function foo() public pure {
  705. print("hi!");
  706. }
  707. }
  708. "#,
  709. true,
  710. false,
  711. );
  712. runtime.constructor(0, vec![]);
  713. runtime.function("test", vec![]);
  714. assert_eq!(
  715. &runtime.debug_buffer(),
  716. r##"call: instantiation_nonce=2,
  717. call: seal_instantiate=0,
  718. print: hi!,
  719. call: seal_debug_message=0,
  720. call: seal_call=0,
  721. "##
  722. );
  723. }
  724. #[test]
  725. fn selector() {
  726. let mut runtime = build_solidity_with_options(
  727. r##"
  728. contract c {
  729. function g() pure public returns (bytes4) {
  730. return this.f.selector ^ this.x.selector;
  731. }
  732. function f() public pure {}
  733. function x() public pure {}
  734. }"##,
  735. false,
  736. true,
  737. );
  738. runtime.function("g", vec![]);
  739. runtime.contracts()[0].code.messages["f"]
  740. .iter()
  741. .zip(&runtime.contracts()[0].code.messages["x"])
  742. .map(|(f, x)| f ^ x)
  743. .zip(runtime.output())
  744. .for_each(|(actual, expected)| assert_eq!(actual, expected));
  745. }
  746. #[test]
  747. fn call_flags() {
  748. let src = r##"
  749. contract Flagger {
  750. uint8 roundtrips = 0;
  751. // Reentrancy is required for reaching the `foo` function for itself.
  752. //
  753. // Cloning and forwarding should have the effect of calling this function again, regardless of what _address was passed.
  754. // Furthermore:
  755. // Cloning the clone should work together with reentrancy.
  756. // Forwarding the input should fail caused by reading the input more than once in the loop
  757. // Tail call should work with any combination of input forwarding.
  758. function echo(
  759. address _address,
  760. uint32 _x,
  761. uint32 _flags
  762. ) public payable returns(uint32 ret) {
  763. for (uint n = 0; n < 2; n++) {
  764. if (roundtrips > 1) {
  765. return _x;
  766. }
  767. roundtrips += 1;
  768. bytes input = abi.encode(bytes4(0), _x);
  769. (bool ok, bytes raw) = _address.call{flags: _flags}(input);
  770. require(ok);
  771. ret = abi.decode(raw, (uint32));
  772. roundtrips -= 1;
  773. }
  774. }
  775. @selector([0,0,0,0])
  776. function foo(uint32 x) public pure returns(uint32) {
  777. return x;
  778. }
  779. // Yields different result for tail calls
  780. function tail_call_it(
  781. address _address,
  782. uint32 _x,
  783. uint32 _flags
  784. ) public returns(uint32 ret) {
  785. bytes input = abi.encode(bytes4(0), _x);
  786. (bool ok, bytes raw) = _address.call{flags: _flags}(input);
  787. require(ok);
  788. ret = abi.decode(raw, (uint32));
  789. ret += 1;
  790. }
  791. }"##;
  792. let forward_input = 0b1u32;
  793. let clone_input = 0b10u32;
  794. let tail_call = 0b100u32;
  795. let allow_reentry = 0b1000u32;
  796. let mut runtime = build_solidity(src);
  797. let address = runtime.caller();
  798. let voyager = 123456789;
  799. let with_flags = |flags| (address, voyager, flags).encode();
  800. // Should work with the reentrancy flag
  801. runtime.function("echo", with_flags(allow_reentry));
  802. assert_eq!(u32::decode(&mut &runtime.output()[..]).unwrap(), voyager);
  803. // Should work with the reentrancy and the tail call flag
  804. runtime.function("echo", with_flags(allow_reentry | tail_call));
  805. assert_eq!(u32::decode(&mut &runtime.output()[..]).unwrap(), voyager);
  806. runtime.constructor(0, vec![]); // Call the storage initializer after tail_call
  807. // Should work with the reentrancy and the clone input
  808. runtime.function("echo", with_flags(allow_reentry | clone_input));
  809. assert_eq!(u32::decode(&mut &runtime.output()[..]).unwrap(), voyager);
  810. // Should work with the reentrancy clone input and tail call flag
  811. runtime.function("echo", with_flags(allow_reentry | clone_input | tail_call));
  812. assert_eq!(u32::decode(&mut &runtime.output()[..]).unwrap(), voyager);
  813. runtime.constructor(0, vec![]); // Reset counter in storage after tail call
  814. // Should fail without the reentrancy flag
  815. runtime.function_expect_failure("echo", with_flags(0));
  816. runtime.constructor(0, vec![]); // Reset counter in storage after fail
  817. runtime.function_expect_failure("echo", with_flags(tail_call));
  818. runtime.constructor(0, vec![]); // Reset counter in storage after fail
  819. // Should fail with input forwarding
  820. runtime.function_expect_failure("echo", with_flags(allow_reentry | forward_input));
  821. runtime.constructor(0, vec![]); // Reset counter in storage after fail
  822. // Test the tail call without setting it
  823. runtime.function("tail_call_it", with_flags(allow_reentry));
  824. assert_eq!(
  825. u32::decode(&mut &runtime.output()[..]).unwrap(),
  826. voyager + 1
  827. );
  828. // Test the tail call with setting it
  829. runtime.function("tail_call_it", with_flags(allow_reentry | tail_call));
  830. assert_eq!(u32::decode(&mut &runtime.output()[..]).unwrap(), voyager);
  831. runtime.constructor(0, vec![]); // Call the storage initializer after tail_call
  832. }
  833. #[test]
  834. fn constructors_and_messages_distinct_in_dispatcher() {
  835. let mut runtime = build_solidity(
  836. r##"
  837. contract c {
  838. @selector([0, 1, 2, 3])
  839. constructor() {}
  840. @selector([4, 5, 6, 7])
  841. function foo() public pure {}
  842. }"##,
  843. );
  844. let constructor = vec![0, 1, 2, 3];
  845. // Given this constructor selector works as intended
  846. runtime.raw_constructor(constructor.clone());
  847. // Expect calling the constructor via "call" to trap the contract
  848. runtime.raw_function_failure(constructor);
  849. let function = vec![4, 5, 6, 7];
  850. // Given this function selector works as intended
  851. runtime.raw_function(function.clone());
  852. // Expect calling the function via "deploy" to trap the contract
  853. runtime.raw_constructor_failure(function);
  854. }
  855. #[test]
  856. fn error_bubbling() {
  857. let mut runtime = build_solidity(
  858. r##"contract C {
  859. function raw_call() public payable returns (bytes ret) {
  860. B b = new B();
  861. (bool ok, ret) = address(b).call{value: 5000}(bytes4(0x00000000));
  862. }
  863. function normal_call() public payable {
  864. B b = new B();
  865. b.b();
  866. }
  867. function ext_func_call() public payable {
  868. A a = new A();
  869. function() external payable func = a.a;
  870. func{value: 1000}();
  871. a.a();
  872. }
  873. }
  874. contract B {
  875. @selector([0, 0, 0, 0])
  876. function b() public payable {
  877. A a = new A();
  878. a.a();
  879. }
  880. }
  881. contract A {
  882. function a() public payable {
  883. revert("no");
  884. }
  885. }
  886. "##,
  887. );
  888. runtime.set_transferred_value(20000);
  889. let expected_output = ([0x08u8, 0xc3, 0x79, 0xa0], "no".to_string()).encode();
  890. // The raw call must not bubble up
  891. runtime.function("raw_call", vec![]);
  892. assert_eq!(runtime.output(), expected_output.encode());
  893. runtime.function_expect_failure("normal_call", vec![]);
  894. assert_eq!(runtime.output(), expected_output);
  895. assert!(runtime.debug_buffer().contains("external call failed"));
  896. runtime.function_expect_failure("ext_func_call", vec![]);
  897. assert_eq!(runtime.output(), expected_output);
  898. assert!(runtime.debug_buffer().contains("external call failed"));
  899. }
  900. #[test]
  901. fn constructor_reverts_bubbling() {
  902. let mut runtime = build_solidity(
  903. r##"
  904. contract A {
  905. B public b;
  906. constructor(bool r) payable {
  907. b = new B(r);
  908. }
  909. }
  910. contract B {
  911. C public c;
  912. constructor(bool r) payable {
  913. c = new C(r);
  914. }
  915. }
  916. contract C {
  917. uint public foo;
  918. constructor(bool r) {
  919. if (!r) revert("no");
  920. }
  921. }"##,
  922. );
  923. runtime.set_transferred_value(20000);
  924. runtime.constructor(0, true.encode());
  925. let mut input = runtime.contracts()[0].code.constructors[0].clone();
  926. input.push(0);
  927. runtime.raw_constructor_failure(input);
  928. let expected_output = ([0x08u8, 0xc3, 0x79, 0xa0], "no".to_string()).encode();
  929. assert_eq!(runtime.output(), expected_output);
  930. }
  931. #[test]
  932. fn try_catch_uncaught_bubbles_up() {
  933. let mut runtime = build_solidity(
  934. r##"contract C {
  935. function c() public payable {
  936. B b = new B();
  937. b.b{value: 1000}();
  938. }
  939. }
  940. contract B {
  941. function b() public payable {
  942. A a = new A();
  943. try a.a(0) {} catch Error(string) {}
  944. }
  945. }
  946. contract A {
  947. function a(uint div) public pure returns(uint) {
  948. return 123 / div;
  949. }
  950. }
  951. "##,
  952. );
  953. runtime.set_transferred_value(10000);
  954. runtime.function_expect_failure("c", vec![]);
  955. let panic = PanicCode::DivisionByZero;
  956. let expected_output = (
  957. SolidityError::Panic(panic).selector().to_be_bytes(),
  958. U256::from(panic as u8),
  959. )
  960. .encode();
  961. assert_eq!(runtime.output(), expected_output);
  962. assert!(runtime.debug_buffer().contains("external call failed"));
  963. }
  964. #[test]
  965. fn try_catch_transfer_fail() {
  966. let mut runtime = build_solidity_with_options(
  967. r#"contract runner {
  968. function test(uint128 amount) public returns (bytes) {
  969. try new aborting{value: amount}(true) returns (
  970. aborting a
  971. ) {} catch Error(string x) {
  972. return hex"41";
  973. } catch (bytes raw) {
  974. return raw;
  975. }
  976. return hex"ff";
  977. }
  978. }
  979. contract aborting {
  980. constructor(bool abort) {
  981. if (abort) {
  982. revert("bar");
  983. }
  984. }
  985. function foo() public pure {}
  986. }"#,
  987. true,
  988. true,
  989. );
  990. // Expect the contract to catch the reverting child constructor
  991. runtime.function("test", 0u128.encode());
  992. assert_eq!(runtime.output(), vec![0x41u8].encode());
  993. assert!(runtime.debug_buffer().contains("seal_instantiate=2"));
  994. // Trying to instantiate with value while having insufficient funds result in
  995. // seal_instantiate failing with transfer failed (return code 5).
  996. // Now, the "catch (bytes raw)" clause should catch that, because there is no
  997. // return data to be decoded.
  998. runtime.function("test", 1u128.encode());
  999. assert_eq!(runtime.output(), Vec::<u8>::new().encode());
  1000. assert!(runtime.debug_buffer().contains("seal_instantiate=5"));
  1001. }