unused_variable_detection.rs 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193
  1. use solang::file_resolver::FileResolver;
  2. use solang::sema::ast;
  3. use solang::{parse_and_resolve, Target};
  4. use std::ffi::OsStr;
  5. fn parse(src: &'static str) -> ast::Namespace {
  6. let mut cache = FileResolver::new();
  7. cache.set_file_contents("test.sol", src.to_string());
  8. parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::Ewasm)
  9. }
  10. fn parse_two_files(src1: &'static str, src2: &'static str) -> ast::Namespace {
  11. let mut cache = FileResolver::new();
  12. cache.set_file_contents("test.sol", src1.to_string());
  13. cache.set_file_contents("test2.sol", src2.to_string());
  14. parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::Ewasm)
  15. }
  16. #[test]
  17. fn emit_event() {
  18. //Used event
  19. let case_1 = r#"
  20. contract usedEvent {
  21. event Hey(uint8 n);
  22. function emitEvent(uint8 n) public {
  23. emit Hey(n);
  24. }
  25. }
  26. "#;
  27. let ns = parse(case_1);
  28. assert_eq!(ns.diagnostics.count_warnings(), 0);
  29. // Unused event
  30. let case_2 = r#"
  31. event Hey(uint8 n);
  32. contract usedEvent {
  33. event Hey(uint8 n);
  34. event Hello(uint8 n);
  35. function emitEvent(uint8 n) public {
  36. emit Hey(n);
  37. }
  38. }
  39. "#;
  40. let ns = parse(case_2);
  41. assert_eq!(ns.diagnostics.count_warnings(), 1);
  42. assert_eq!(
  43. ns.diagnostics.first_warning().message,
  44. "event 'Hello' has never been emitted"
  45. );
  46. // Unused event
  47. let case_2 = r#"
  48. contract F {
  49. event Hey(uint8 n);
  50. event Hello(uint8 n);
  51. }
  52. contract usedEvent is F {
  53. event Hey(uint8 n);
  54. function emitEvent(uint8 n) public {
  55. emit Hey(n);
  56. }
  57. }
  58. "#;
  59. let ns = parse(case_2);
  60. assert_eq!(ns.diagnostics.count_warnings(), 1);
  61. assert_eq!(
  62. ns.diagnostics.first_warning().message,
  63. "event 'Hello' has never been emitted"
  64. );
  65. // Unused event
  66. let case_2 = r#"
  67. contract F {
  68. event Hey(uint8 n);
  69. }
  70. contract usedEvent is F {
  71. event Hey(uint8 n);
  72. function emitEvent(uint8 n) public {
  73. // reference event in contract F, so our event decl is not used
  74. emit F.Hey(n);
  75. }
  76. }
  77. "#;
  78. let ns = parse(case_2);
  79. assert_eq!(ns.diagnostics.count_warnings(), 1);
  80. assert_eq!(
  81. ns.diagnostics.first_warning().message,
  82. "event 'Hey' has never been emitted"
  83. );
  84. // make sure we don't complain about interfaces or abstract contracts
  85. let case_3 = r#"
  86. abstract contract F {
  87. event Hey(uint8 n);
  88. }
  89. interface G {
  90. event Hey(uint8 n);
  91. }
  92. "#;
  93. let ns = parse(case_3);
  94. assert_eq!(ns.diagnostics.count_warnings(), 0);
  95. }
  96. #[test]
  97. fn constant_variable() {
  98. let file_2 = r#"
  99. uint32 constant outside = 2;
  100. "#;
  101. let file_1 = r#"
  102. import "test2.sol";
  103. contract Testing {
  104. uint32 test;
  105. uint32 constant cte = 5;
  106. constructor() {
  107. test = outside;
  108. test = cte;
  109. }
  110. function get() public view returns (uint32) {
  111. return test;
  112. }
  113. }
  114. "#;
  115. //Constant properly read
  116. let ns = parse_two_files(file_1, file_2);
  117. assert_eq!(ns.diagnostics.count_warnings(), 0);
  118. let file_1 = r#"
  119. import "test2.sol";
  120. contract Testing {
  121. uint32 test;
  122. uint32 constant cte = 5;
  123. constructor() {
  124. test = 45;
  125. }
  126. function get() public view returns (uint32) {
  127. return test;
  128. }
  129. }
  130. "#;
  131. let ns = parse_two_files(file_1, file_2);
  132. assert_eq!(ns.diagnostics.count_warnings(), 2);
  133. assert!(ns
  134. .diagnostics
  135. .warning_contains("storage variable 'cte' has been assigned, but never read"));
  136. assert!(ns
  137. .diagnostics
  138. .warning_contains("global constant 'outside' has never been used"));
  139. }
  140. #[test]
  141. fn storage_variable() {
  142. let file = r#"
  143. contract Test {
  144. string str = "This is a test";
  145. string str2;
  146. constructor() {
  147. str = "This is another test";
  148. }
  149. }
  150. "#;
  151. let ns = parse(file);
  152. let warnings = ns.diagnostics.warnings();
  153. assert_eq!(warnings.len(), 2);
  154. assert_eq!(
  155. warnings[0].message,
  156. "storage variable 'str' has been assigned, but never read"
  157. );
  158. assert_eq!(
  159. warnings[1].message,
  160. "storage variable 'str2' has never been used"
  161. );
  162. let file = r#"
  163. contract Test {
  164. string str = "This is a test";
  165. string str2;
  166. constructor() {
  167. str = "This is another test";
  168. str2 = str;
  169. }
  170. }
  171. "#;
  172. let ns = parse(file);
  173. assert_eq!(ns.diagnostics.count_warnings(), 1);
  174. assert_eq!(
  175. ns.diagnostics.first_warning().message,
  176. "storage variable 'str2' has been assigned, but never read"
  177. );
  178. let file = r#"
  179. contract Test {
  180. string str = "This is a test";
  181. constructor() {
  182. str = "This is another test";
  183. }
  184. }
  185. contract Test2 is Test {
  186. function get() public view returns (string) {
  187. return str;
  188. }
  189. }
  190. "#;
  191. let ns = parse(file);
  192. assert_eq!(ns.diagnostics.count_warnings(), 0);
  193. }
  194. #[test]
  195. fn state_variable() {
  196. let file = r#"
  197. contract Test {
  198. function get() public pure {
  199. uint32 a = 1;
  200. uint32 b;
  201. b = 1;
  202. uint32 c;
  203. uint32 d;
  204. d = 1;
  205. uint32 e;
  206. e = d*5;
  207. d = e/5;
  208. }
  209. }
  210. "#;
  211. let ns = parse(file);
  212. assert_eq!(ns.diagnostics.count_warnings(), 3);
  213. assert!(ns
  214. .diagnostics
  215. .warning_contains("local variable 'b' has been assigned, but never read"));
  216. assert!(ns
  217. .diagnostics
  218. .warning_contains("local variable 'a' has been assigned, but never read"));
  219. assert!(ns
  220. .diagnostics
  221. .warning_contains("local variable 'c' has never been read nor assigned"));
  222. }
  223. #[test]
  224. fn struct_usage() {
  225. let file = r#"
  226. struct testing {
  227. uint8 it;
  228. bool tf;
  229. }
  230. contract Test {
  231. testing t1;
  232. testing t4;
  233. testing t6;
  234. constructor() {
  235. t1 = testing(8, false);
  236. }
  237. function modify() public returns (uint8) {
  238. testing memory t2;
  239. t2.it = 4;
  240. t4 = testing(1, true);
  241. testing storage t3 = t4;
  242. uint8 k = 2*4/t3.it;
  243. testing t5;
  244. return k;
  245. }
  246. }
  247. "#;
  248. let ns = parse(file);
  249. assert_eq!(ns.diagnostics.count_warnings(), 4);
  250. assert!(ns
  251. .diagnostics
  252. .warning_contains("local variable 't2' has been assigned, but never read"));
  253. assert!(ns
  254. .diagnostics
  255. .warning_contains("storage variable 't1' has been assigned, but never read"));
  256. assert!(ns
  257. .diagnostics
  258. .warning_contains("local variable 't5' has never been read nor assigned"));
  259. assert!(ns
  260. .diagnostics
  261. .warning_contains("storage variable 't6' has never been used"));
  262. }
  263. #[test]
  264. fn subscript() {
  265. let file = r#"
  266. contract Test {
  267. int[] arr1;
  268. int[4] arr2;
  269. int[4] arr3;
  270. bytes byteArr;
  271. uint constant e = 1;
  272. function get() public {
  273. uint8 a = 1;
  274. uint8 b = 2;
  275. arr1[a] = 1;
  276. arr2[a+b] = 2;
  277. uint8 c = 1;
  278. uint8 d = 1;
  279. int[] memory arr4;
  280. arr4[0] = 1;
  281. int[4] storage arr5 = arr3;
  282. arr5[c*d] = 1;
  283. byteArr[e] = 0x05;
  284. }
  285. }
  286. "#;
  287. let ns = parse(file);
  288. assert_eq!(ns.diagnostics.count_warnings(), 4);
  289. assert!(ns
  290. .diagnostics
  291. .warning_contains("local variable 'arr4' has been assigned, but never read"));
  292. assert!(ns
  293. .diagnostics
  294. .warning_contains("storage variable 'arr1' has been assigned, but never read"));
  295. assert!(ns
  296. .diagnostics
  297. .warning_contains("storage variable 'arr2' has been assigned, but never read"));
  298. assert!(ns
  299. .diagnostics
  300. .warning_contains("storage variable 'byteArr' has been assigned, but never read"));
  301. let file = r#"
  302. contract Test {
  303. int[] arr1;
  304. int[4] arr2;
  305. int[4] arr3;
  306. bytes byteArr;
  307. uint constant e = 1;
  308. function get() public {
  309. uint8 a = 1;
  310. uint8 b = 2;
  311. arr1[a] = 1;
  312. arr2[a+b] = 2;
  313. assert(arr1[a] == arr2[b]);
  314. uint8 c = 1;
  315. uint8 d = 1;
  316. int[] memory arr4;
  317. arr4[0] = 1;
  318. int[4] storage arr5 = arr3;
  319. arr5[c*d] = 1;
  320. assert(arr4[c] == arr5[d]);
  321. assert(arr3[c] == arr5[d]);
  322. byteArr[e] = 0x05;
  323. assert(byteArr[e] == byteArr[e]);
  324. }
  325. }
  326. "#;
  327. let ns = parse(file);
  328. assert_eq!(ns.diagnostics.count_warnings(), 0);
  329. }
  330. #[test]
  331. fn assign_trunc_cast() {
  332. //This covers ZeroExt as well
  333. let file = r#"
  334. contract Test {
  335. bytes byteArr;
  336. bytes32 baRR;
  337. function get() public {
  338. string memory s = "Test";
  339. byteArr = bytes(s);
  340. uint16 a = 1;
  341. uint8 b;
  342. b = uint8(a);
  343. uint256 c;
  344. c = b;
  345. bytes32 b32;
  346. bytes memory char = bytes(bytes32(uint(a) * 2 ** (8 * b)));
  347. baRR = bytes32(c);
  348. bytes32 cdr = bytes32(char);
  349. assert(b32 == baRR);
  350. if(b32 != cdr) {
  351. }
  352. }
  353. }
  354. "#;
  355. let ns = parse(file);
  356. assert_eq!(ns.diagnostics.count_warnings(), 1);
  357. assert!(ns
  358. .diagnostics
  359. .warning_contains("storage variable 'byteArr' has been assigned, but never read"));
  360. }
  361. #[test]
  362. fn array_length() {
  363. let file = r#"
  364. contract Test {
  365. int[5] arr1;
  366. int[] arr2;
  367. function get() public view returns (bool) {
  368. int[5] memory arr3;
  369. int[] memory arr4;
  370. bool test = false;
  371. if(arr1.length == arr2.length) {
  372. test = true;
  373. }
  374. else if(arr3.length != arr4.length) {
  375. test = false;
  376. }
  377. return test;
  378. }
  379. }
  380. "#;
  381. let ns = parse(file);
  382. assert_eq!(ns.diagnostics.count_warnings(), 0);
  383. }
  384. #[test]
  385. fn sign_ext_storage_load() {
  386. let file = r#"
  387. contract Test {
  388. bytes a;
  389. function use(bytes memory b) pure public {
  390. assert(b[0] == b[1]);
  391. }
  392. function get() public pure returns (int16 ret) {
  393. use(a);
  394. int8 b = 1;
  395. int16 c = 1;
  396. int16 d;
  397. d = c << b;
  398. ret = d;
  399. }
  400. }
  401. "#;
  402. let ns = parse(file);
  403. assert_eq!(ns.diagnostics.count_warnings(), 0);
  404. }
  405. #[test]
  406. fn statements() {
  407. let file = r#"
  408. contract AddNumbers { function add(uint256 a, uint256 b) external pure returns (uint256 c) {c = b;} }
  409. contract Example {
  410. AddNumbers addContract;
  411. event StringFailure(string stringFailure);
  412. event BytesFailure(bytes bytesFailure);
  413. function exampleFunction(uint256 _a, uint256 _b) public returns (uint256 _c) {
  414. try addContract.add(_a, _b) returns (uint256 _value) {
  415. return (_value);
  416. } catch Error(string memory _err) {
  417. // This may occur if there is an overflow with the two numbers and the `AddNumbers` contract explicitly fails with a `revert()`
  418. emit StringFailure(_err);
  419. } catch (bytes memory _err) {
  420. emit BytesFailure(_err);
  421. }
  422. }
  423. function testFunction() pure public {
  424. int three = 3;
  425. {
  426. int test = 2;
  427. int c = test*3;
  428. while(c != test) {
  429. c -= three;
  430. }
  431. }
  432. int four = 4;
  433. int test = 3;
  434. do {
  435. int ct = 2;
  436. } while(four > test);
  437. }
  438. function bytesToUInt(uint v) public pure returns (uint ret) {
  439. if (v == 0) {
  440. ret = 0;
  441. }
  442. else {
  443. while (v > 0) {
  444. ret = uint(uint(ret) / (2 ** 8));
  445. ret |= uint(((v % 10) + 48) * 2 ** (8 * 31));
  446. v /= 10;
  447. }
  448. }
  449. return ret;
  450. }
  451. function stringToUint(string s) public pure returns (uint result) {
  452. bytes memory b = bytes(s);
  453. uint i;
  454. result = 0;
  455. for (i = 0; i < b.length; i++) {
  456. uint c = uint(b[i]);
  457. if (c >= 48 && c <= 57) {
  458. result = result * 10 + (c - 48);
  459. }
  460. }
  461. }
  462. }
  463. "#;
  464. let ns = parse(file);
  465. assert_eq!(ns.diagnostics.count_warnings(), 2);
  466. assert!(ns
  467. .diagnostics
  468. .warning_contains("function parameter 'a' has never been read"));
  469. assert!(ns
  470. .diagnostics
  471. .warning_contains("local variable 'ct' has been assigned, but never read",));
  472. }
  473. #[test]
  474. fn function_call() {
  475. let file = r#"
  476. contract Test1 {
  477. uint32 public a;
  478. constructor(uint32 b) {
  479. a = b;
  480. }
  481. }
  482. contract Test2{
  483. function test(uint32 v1, uint32 v2) private returns (uint32) {
  484. uint32 v = 1;
  485. Test1 t = new Test1(v);
  486. uint32[2] memory vec = [v2, v1];
  487. return vec[0] + t.a();
  488. }
  489. function callTest() public {
  490. uint32 ta = 1;
  491. uint32 tb = 2;
  492. ta = test(ta, tb);
  493. }
  494. }
  495. contract C {
  496. uint public data;
  497. function x() public returns (uint) {
  498. data = 3;
  499. return this.data();
  500. }
  501. }
  502. "#;
  503. let ns = parse(file);
  504. assert_eq!(ns.diagnostics.count_warnings(), 0);
  505. let file = r#"
  506. contract Test1 {
  507. uint32 public a;
  508. constructor(uint32 b) {
  509. a = b;
  510. }
  511. }
  512. contract Test2 is Test1{
  513. constructor(uint32 val) Test1(val) {}
  514. function test(uint32 v1, uint32 v2) private returns (uint32) {
  515. uint32 v = 1;
  516. Test1 t = new Test1(v);
  517. uint32[2] memory vec = [v2, v1];
  518. return vec[0] + t.a();
  519. }
  520. function callTest() public {
  521. uint32 ta = 1;
  522. uint32 tb = 2;
  523. ta = test(ta, tb);
  524. }
  525. }
  526. "#;
  527. let ns = parse(file);
  528. assert_eq!(ns.diagnostics.count_warnings(), 0);
  529. }
  530. #[test]
  531. fn array_push_pop() {
  532. let file = r#"
  533. contract Test1 {
  534. uint32[] vec1;
  535. function testVec() public {
  536. uint32 a = 1;
  537. uint32 b = 2;
  538. uint32[] memory vec2;
  539. vec1.push(a);
  540. vec2.push(b);
  541. }
  542. }
  543. "#;
  544. let ns = parse(file);
  545. assert_eq!(ns.diagnostics.count_warnings(), 2);
  546. assert!(ns
  547. .diagnostics
  548. .warning_contains("local variable 'vec2' has been assigned, but never read"));
  549. assert!(ns
  550. .diagnostics
  551. .warning_contains("storage variable 'vec1' has been assigned, but never read"));
  552. let file = r#"
  553. contract Test1 {
  554. uint32[] vec1;
  555. function testVec() public {
  556. uint32 a = 1;
  557. uint32 b = 2;
  558. uint32[] memory vec2;
  559. vec1.push(a);
  560. vec2.push(b);
  561. vec1.pop();
  562. vec2.pop();
  563. }
  564. }
  565. "#;
  566. let ns = parse(file);
  567. assert_eq!(ns.diagnostics.count_warnings(), 0);
  568. }
  569. #[test]
  570. fn return_variable() {
  571. let file = r#"
  572. contract Test1 {
  573. string testing;
  574. function test1() public pure returns (uint32 ret, string memory ret2) {
  575. return (2, "Testing is fun");
  576. }
  577. function test2() public returns (uint32 hey) {
  578. (uint32 a, string memory t) = test1();
  579. testing = t;
  580. }
  581. }
  582. "#;
  583. let ns = parse(file);
  584. assert_eq!(ns.diagnostics.count_warnings(), 3);
  585. assert!(ns
  586. .diagnostics
  587. .warning_contains("destructure variable 'a' has never been used"));
  588. assert!(ns
  589. .diagnostics
  590. .warning_contains("return variable 'hey' has never been assigned"));
  591. assert!(ns
  592. .diagnostics
  593. .warning_contains("storage variable 'testing' has been assigned, but never read"));
  594. }
  595. #[test]
  596. fn try_catch() {
  597. let file = r#"
  598. contract CalledContract {}
  599. contract TryCatcher {
  600. event SuccessEvent(bool t);
  601. event CatchEvent(bool t);
  602. function execute() public {
  603. try new CalledContract() returns(CalledContract returnedInstance) {
  604. emit SuccessEvent(true);
  605. } catch Error(string memory revertReason) {
  606. emit CatchEvent(true);
  607. } catch (bytes memory returnData) {
  608. emit CatchEvent(false);
  609. }
  610. }
  611. }
  612. "#;
  613. let ns = parse(file);
  614. assert_eq!(ns.diagnostics.count_warnings(), 3);
  615. assert!(ns
  616. .diagnostics
  617. .warning_contains("try-catch error bytes 'returnData' has never been used"));
  618. assert!(ns
  619. .diagnostics
  620. .warning_contains("try-catch returns variable 'returnedInstance' has never been read"));
  621. assert!(ns
  622. .diagnostics
  623. .warning_contains("try-catch error string 'revertReason' has never been used"));
  624. let file = r#"
  625. contract CalledContract {
  626. bool public ok = true;
  627. bool private notOk = false;
  628. }
  629. contract TryCatcher {
  630. event SuccessEvent(bool t);
  631. event CatchEvent(string t);
  632. event CatchBytes(bytes t);
  633. function execute() public {
  634. try new CalledContract() returns(CalledContract returnedInstance) {
  635. // returnedInstance can be used to obtain the address of the newly deployed contract
  636. emit SuccessEvent(returnedInstance.ok());
  637. } catch Error(string memory revertReason) {
  638. emit CatchEvent(revertReason);
  639. } catch (bytes memory returnData) {
  640. emit CatchBytes(returnData);
  641. }
  642. }
  643. }
  644. "#;
  645. let ns = parse(file);
  646. assert_eq!(ns.diagnostics.count_warnings(), 1);
  647. assert!(ns
  648. .diagnostics
  649. .warning_contains("storage variable 'notOk' has been assigned, but never read"));
  650. let file = r#"
  651. contract CalledContract {
  652. bool public ok;
  653. }
  654. "#;
  655. let ns = parse(file);
  656. assert_eq!(ns.diagnostics.count_warnings(), 0);
  657. }
  658. #[test]
  659. fn destructure() {
  660. let file = r#"
  661. contract Test2{
  662. function callTest() public view returns (uint32 ret) {
  663. uint32 ta = 1;
  664. uint32 tb = 2;
  665. uint32 te = 3;
  666. string memory tc = "hey";
  667. bytes memory td = bytes(tc);
  668. address nameReg = address(this);
  669. (bool tf,) = nameReg.call(td);
  670. ta = tf? tb : te;
  671. uint8 tg = 1;
  672. uint8 th = 2;
  673. (tg, th) = (th, tg);
  674. return ta;
  675. }
  676. }
  677. "#;
  678. let ns = parse(file);
  679. assert_eq!(ns.diagnostics.count_warnings(), 0);
  680. }
  681. #[test]
  682. fn struct_initialization() {
  683. let file = r#"
  684. contract Test1{
  685. struct Test2{
  686. uint8 a;
  687. uint8 b;
  688. }
  689. function callTest() public pure returns (uint32 ret) {
  690. uint8 tg = 1;
  691. uint8 th = 2;
  692. Test2 memory t2;
  693. t2 = Test2(tg, th);
  694. ret = t2.a;
  695. }
  696. }
  697. "#;
  698. let ns = parse(file);
  699. assert_eq!(ns.diagnostics.count_warnings(), 0);
  700. }
  701. #[test]
  702. fn subarray_mapping_struct_literal() {
  703. let file = r#"
  704. contract T {
  705. int p;
  706. constructor(int b) {
  707. p = b;
  708. }
  709. function sum(int a, int b) virtual public returns (int){
  710. uint8 v1 = 1;
  711. uint8 v2 = 2;
  712. uint8 v3 = 3;
  713. uint8 v4 = 4;
  714. uint8[2][2] memory v = [[v1, v2], [v3, v4]];
  715. return a + b * p/v[0][1];
  716. }
  717. }
  718. contract Test is T(2){
  719. struct fooStruct {
  720. int foo;
  721. int figther;
  722. }
  723. mapping(string => int) public mp;
  724. enum FreshJuiceSize{ SMALL, MEDIUM, LARGE }
  725. FreshJuiceSize choice;
  726. function sum(int a, int b) override public returns (int) {
  727. choice = FreshJuiceSize.LARGE;
  728. return a*b;
  729. }
  730. function test() public returns (int){
  731. int a = 1;
  732. int b = 2;
  733. int c = super.sum(a, b);
  734. int d = 3;
  735. fooStruct memory myStruct = fooStruct({foo: c, figther: d});
  736. string memory t = "Do some tests";
  737. mp[t] = myStruct.figther;
  738. return mp[t];
  739. }
  740. }
  741. "#;
  742. let ns = parse(file);
  743. assert_eq!(ns.diagnostics.count_warnings(), 1);
  744. assert!(ns
  745. .diagnostics
  746. .warning_contains("storage variable 'choice' has been assigned, but never read"));
  747. }
  748. #[test]
  749. fn builtin_call_destructure() {
  750. let file = r#"
  751. contract Test {
  752. function test() public returns(bool p) {
  753. uint128 b = 1;
  754. uint64 g = 2;
  755. address payable ad = payable(address(this));
  756. bytes memory by = hex"AB2";
  757. (p, ) = ad.call{value: b, gas: g}(by);
  758. uint c = 1;
  759. abi.encodeWithSignature("hey", c);
  760. uint128 amount = 2;
  761. ad.send(amount);
  762. uint128 amount2 = 1;
  763. ad.transfer(amount2);
  764. }
  765. }
  766. "#;
  767. let ns = parse(file);
  768. assert_eq!(ns.diagnostics.count_warnings(), 0);
  769. }
  770. #[test]
  771. fn delete_statement() {
  772. let file = r#"
  773. pragma solidity 0;
  774. contract Test1{
  775. int test8var;
  776. function test8() public {
  777. delete test8var;
  778. test8var = 2;
  779. }
  780. }
  781. "#;
  782. let ns = parse(file);
  783. assert_eq!(ns.diagnostics.count_warnings(), 0);
  784. }
  785. #[test]
  786. fn load_length() {
  787. let file = r#"
  788. contract foo {
  789. function f(uint i1) public pure returns (int) {
  790. int[8] bar = [ int(10), 20, 30, 4, 5, 6, 7, 8 ];
  791. bar[2] = 0x7_f;
  792. return bar[i1];
  793. }
  794. function barfunc() public pure returns (uint) {
  795. uint[2][3][4] array;
  796. return array.length;
  797. }
  798. }
  799. "#;
  800. let ns = parse(file);
  801. assert_eq!(ns.diagnostics.count_warnings(), 0);
  802. }
  803. #[test]
  804. fn address_selector() {
  805. let file = r#"
  806. contract ctc {
  807. function foo(int32 a) public pure returns (bool) {
  808. return a==1;
  809. }
  810. function test() public view {
  811. function(int32) external returns (bool) func = this.foo;
  812. assert(address(this) == func.address);
  813. assert(func.selector == hex"42761137");
  814. }
  815. }
  816. "#;
  817. let ns = parse(file);
  818. assert_eq!(ns.diagnostics.count_warnings(), 0);
  819. }
  820. #[test]
  821. fn load_storage_load() {
  822. let file = r#"
  823. struct X {
  824. uint32 f1;
  825. bool f2;
  826. }
  827. contract foo {
  828. function get() public pure returns (X[4] f) {
  829. f[1].f1 = 102;
  830. f[1].f2 = true;
  831. }
  832. }
  833. "#;
  834. let ns = parse(file);
  835. assert_eq!(ns.diagnostics.count_warnings(), 0);
  836. }
  837. #[test]
  838. fn variable_function() {
  839. let file = r#"
  840. contract ft is Arith {
  841. function test(bool action, int32 a, int32 b) public returns (int32) {
  842. function(int32,int32) internal returns (int32) func;
  843. if (action) {
  844. func = Arith.mul;
  845. } else {
  846. func = Arith.add;
  847. }
  848. return func(a, b);
  849. }
  850. }
  851. contract Arith {
  852. function mul(int32 a, int32 b) internal pure returns (int32) {
  853. return a * b;
  854. }
  855. function add(int32 a, int32 b) internal pure returns (int32) {
  856. return a + b;
  857. }
  858. }
  859. "#;
  860. let ns = parse(file);
  861. assert_eq!(ns.diagnostics.count_warnings(), 0);
  862. let file = r#"
  863. contract ft {
  864. function test() public {
  865. function(int32) external returns (uint64) func = this.foo;
  866. assert(func(102) == 0xabbaabba);
  867. }
  868. function foo(int32) public pure returns (uint64) {
  869. return 0xabbaabba;
  870. }
  871. }
  872. "#;
  873. let ns = parse(file);
  874. assert_eq!(ns.diagnostics.count_warnings(), 0);
  875. let file = r#"
  876. contract ft {
  877. function(int32,int32) internal returns (int32) func;
  878. function mul(int32 a, int32 b) internal pure returns (int32) {
  879. return a * b;
  880. }
  881. function add(int32 a, int32 b) internal pure returns (int32) {
  882. return a + b;
  883. }
  884. function set_op(bool action) public {
  885. if (action) {
  886. func = mul;
  887. } else {
  888. func = add;
  889. }
  890. }
  891. function test(int32 a, int32 b) public returns (int32) {
  892. return func(a, b);
  893. }
  894. }
  895. "#;
  896. let ns = parse(file);
  897. assert_eq!(ns.diagnostics.count_warnings(), 0);
  898. let file = r#"
  899. contract ft {
  900. function mul(int32 a, int32 b) internal pure returns (int32) {
  901. return a * b;
  902. }
  903. function add(int32 a, int32 b) internal pure returns (int32) {
  904. return a + b;
  905. }
  906. function test(bool action, int32 a, int32 b) public returns (int32) {
  907. function(int32,int32) internal returns (int32) func;
  908. if (action) {
  909. func = mul;
  910. } else {
  911. func = add;
  912. }
  913. return func(a, b);
  914. }
  915. }
  916. "#;
  917. let ns = parse(file);
  918. assert_eq!(ns.diagnostics.count_warnings(), 0);
  919. let file = r#"
  920. contract ft is Arith {
  921. function mul(int32 a, int32 b) internal pure override returns (int32) {
  922. return a * b * 10;
  923. }
  924. function add(int32 a, int32 b) internal pure override returns (int32) {
  925. return a + b + 10;
  926. }
  927. }
  928. contract Arith {
  929. function test(bool action, int32 a, int32 b) public returns (int32) {
  930. function(int32,int32) internal returns (int32) func;
  931. if (action) {
  932. func = mul;
  933. } else {
  934. func = add;
  935. }
  936. return func(a, b);
  937. }
  938. function mul(int32 a, int32 b) internal virtual returns (int32) {
  939. return a * b;
  940. }
  941. function add(int32 a, int32 b) internal virtual returns (int32) {
  942. return a + b;
  943. }
  944. }
  945. "#;
  946. let ns = parse(file);
  947. assert_eq!(ns.diagnostics.count_warnings(), 0);
  948. let file = r#"
  949. function global_function() pure returns (uint32) {
  950. return 102;
  951. }
  952. function global_function2() pure returns (uint32) {
  953. return global_function() + 5;
  954. }
  955. contract c {
  956. function test() public {
  957. function() internal returns (uint32) ftype = global_function2;
  958. uint64 x = ftype();
  959. assert(x == 107);
  960. }
  961. }
  962. "#;
  963. let ns = parse(file);
  964. assert_eq!(ns.diagnostics.count_warnings(), 0);
  965. }
  966. #[test]
  967. fn format_string() {
  968. let file = r#"
  969. contract foo {
  970. constructor() {
  971. int x = 21847450052839212624230656502990235142567050104912751880812823948662932355201;
  972. print("x = {}".format(x));
  973. }
  974. }
  975. "#;
  976. let ns = parse(file);
  977. assert_eq!(ns.diagnostics.count_warnings(), 0);
  978. }
  979. #[test]
  980. fn balance() {
  981. let file = r#"
  982. contract foo {
  983. function test(address payable addr) public pure returns (bool) {
  984. bool p;
  985. p = addr.balance == 2;
  986. return p;
  987. }
  988. }
  989. "#;
  990. let ns = parse(file);
  991. assert_eq!(ns.diagnostics.count_warnings(), 0);
  992. }