contracts.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. use parity_scale_codec::Encode;
  2. use parity_scale_codec_derive::{Decode, Encode};
  3. use crate::{build_solidity, first_error, first_warning, no_errors, parse_and_resolve};
  4. use solang::Target;
  5. #[derive(Debug, PartialEq, Encode, Decode)]
  6. struct RevertReturn(u32, String);
  7. #[test]
  8. fn contract_name() {
  9. let ns = parse_and_resolve(
  10. "contract test {
  11. function test() public {}
  12. }",
  13. Target::Substrate {
  14. address_length: 32,
  15. value_length: 16,
  16. },
  17. );
  18. assert_eq!(
  19. first_error(ns.diagnostics),
  20. "function cannot have same name as the contract"
  21. );
  22. let ns = parse_and_resolve(
  23. "contract test {
  24. enum test { a}
  25. }",
  26. Target::Substrate {
  27. address_length: 32,
  28. value_length: 16,
  29. },
  30. );
  31. assert_eq!(
  32. first_warning(ns.diagnostics),
  33. "test is already defined as a contract name"
  34. );
  35. let ns = parse_and_resolve(
  36. "contract test {
  37. bool test;
  38. }",
  39. Target::Substrate {
  40. address_length: 32,
  41. value_length: 16,
  42. },
  43. );
  44. assert_eq!(
  45. first_warning(ns.diagnostics),
  46. "test is already defined as a contract name"
  47. );
  48. let ns = parse_and_resolve(
  49. "contract test {
  50. struct test { bool a; }
  51. }",
  52. Target::Substrate {
  53. address_length: 32,
  54. value_length: 16,
  55. },
  56. );
  57. assert_eq!(
  58. first_warning(ns.diagnostics),
  59. "test is already defined as a contract name"
  60. );
  61. let ns = parse_and_resolve(
  62. "contract test {
  63. function f() public {
  64. int test;
  65. }
  66. }",
  67. Target::Substrate {
  68. address_length: 32,
  69. value_length: 16,
  70. },
  71. );
  72. assert_eq!(
  73. first_warning(ns.diagnostics),
  74. "declaration of ‘test’ shadows contract name"
  75. );
  76. let ns = parse_and_resolve(
  77. "contract test {
  78. function f(int test) public {
  79. }
  80. }",
  81. Target::Substrate {
  82. address_length: 32,
  83. value_length: 16,
  84. },
  85. );
  86. assert_eq!(
  87. first_warning(ns.diagnostics),
  88. "declaration of ‘test’ shadows contract name"
  89. );
  90. let ns = parse_and_resolve(
  91. "contract test {
  92. function f() public returns (int test) {
  93. return 0;
  94. }
  95. }",
  96. Target::Substrate {
  97. address_length: 32,
  98. value_length: 16,
  99. },
  100. );
  101. assert_eq!(
  102. first_warning(ns.diagnostics),
  103. "declaration of ‘test’ shadows contract name"
  104. );
  105. let ns = parse_and_resolve(
  106. r#"
  107. contract a {
  108. function x() public {
  109. b y = new b();
  110. }
  111. }
  112. contract b {
  113. function x() public {
  114. a y = new a();
  115. }
  116. }
  117. "#,
  118. Target::Substrate {
  119. address_length: 32,
  120. value_length: 16,
  121. },
  122. );
  123. assert_eq!(
  124. first_error(ns.diagnostics),
  125. "circular reference creating contract ‘a’"
  126. );
  127. let ns = parse_and_resolve(
  128. r#"
  129. contract a {
  130. function x() public {
  131. b y = new b();
  132. }
  133. }
  134. contract b {
  135. function x() public {
  136. c y = new c();
  137. }
  138. }
  139. contract c {
  140. function x() public {
  141. a y = new a();
  142. }
  143. }
  144. "#,
  145. Target::Substrate {
  146. address_length: 32,
  147. value_length: 16,
  148. },
  149. );
  150. assert_eq!(
  151. first_error(ns.diagnostics),
  152. "circular reference creating contract ‘a’"
  153. );
  154. }
  155. #[test]
  156. fn contract_type() {
  157. let ns = parse_and_resolve(
  158. r#"
  159. contract printer {
  160. function test() public {
  161. print("In f.test()");
  162. }
  163. }
  164. contract foo {
  165. function test1(printer x) public {
  166. address y = x;
  167. }
  168. function test2(address x) public {
  169. printer y = printer(x);
  170. }
  171. }"#,
  172. Target::Substrate {
  173. address_length: 32,
  174. value_length: 16,
  175. },
  176. );
  177. assert_eq!(
  178. first_error(ns.diagnostics),
  179. "implicit conversion to address from contract printer not allowed"
  180. );
  181. let ns = parse_and_resolve(
  182. r#"
  183. contract printer {
  184. function test() public {
  185. printer x = printer(address(102));
  186. }
  187. }"#,
  188. Target::Substrate {
  189. address_length: 32,
  190. value_length: 16,
  191. },
  192. );
  193. no_errors(ns.diagnostics);
  194. let ns = parse_and_resolve(
  195. r#"
  196. contract printer {
  197. function test() public {
  198. print("In f.test()");
  199. }
  200. }
  201. contract foo {
  202. function test1(printer x) public {
  203. address y = 102;
  204. }
  205. }"#,
  206. Target::Substrate {
  207. address_length: 32,
  208. value_length: 16,
  209. },
  210. );
  211. assert_eq!(
  212. first_error(ns.diagnostics),
  213. "expected ‘address’, found integer"
  214. );
  215. let ns = parse_and_resolve(
  216. r#"
  217. contract printer {
  218. function test() public {
  219. print("In f.test()");
  220. }
  221. }
  222. contract foo {
  223. function test1() public {
  224. printer y = 102;
  225. }
  226. }"#,
  227. Target::Substrate {
  228. address_length: 32,
  229. value_length: 16,
  230. },
  231. );
  232. assert_eq!(
  233. first_error(ns.diagnostics),
  234. "expected ‘contract printer’, found integer"
  235. );
  236. let ns = parse_and_resolve(
  237. r#"
  238. contract printer {
  239. function test() public returns (printer) {
  240. return new printer();
  241. }
  242. }"#,
  243. Target::Substrate {
  244. address_length: 32,
  245. value_length: 16,
  246. },
  247. );
  248. assert_eq!(
  249. first_error(ns.diagnostics),
  250. "new cannot construct current contract ‘printer’"
  251. );
  252. let ns = parse_and_resolve(
  253. r#"
  254. contract printer {
  255. function test() public returns (printer) {
  256. return new printer({});
  257. }
  258. }"#,
  259. Target::Substrate {
  260. address_length: 32,
  261. value_length: 16,
  262. },
  263. );
  264. assert_eq!(
  265. first_error(ns.diagnostics),
  266. "new cannot construct current contract ‘printer’"
  267. );
  268. }
  269. #[test]
  270. fn external_call() {
  271. let ns = parse_and_resolve(
  272. r##"
  273. contract c {
  274. b x;
  275. function test() public returns (int32) {
  276. return x.get_x();
  277. }
  278. }
  279. contract b {
  280. function get_x(int32 t) public returns (int32) {
  281. return 1;
  282. }
  283. }"##,
  284. Target::Substrate {
  285. address_length: 32,
  286. value_length: 16,
  287. },
  288. );
  289. assert_eq!(
  290. first_error(ns.diagnostics),
  291. "function expects 1 arguments, 0 provided"
  292. );
  293. let ns = parse_and_resolve(
  294. r##"
  295. contract c {
  296. b x;
  297. function test() public returns (int32) {
  298. return x.get_x({b: false});
  299. }
  300. }
  301. contract b {
  302. function get_x(int32 t, bool b) public returns (int32) {
  303. return 1;
  304. }
  305. }"##,
  306. Target::Substrate {
  307. address_length: 32,
  308. value_length: 16,
  309. },
  310. );
  311. assert_eq!(
  312. first_error(ns.diagnostics),
  313. "function expects 2 arguments, 1 provided"
  314. );
  315. let ns = parse_and_resolve(
  316. r##"
  317. contract c {
  318. b x;
  319. constructor() public {
  320. x = new b(102);
  321. }
  322. function test() public returns (int32) {
  323. return x.get_x({ t: 10, t: false });
  324. }
  325. }
  326. contract b {
  327. int32 x;
  328. constructor(int32 a) public {
  329. x = a;
  330. }
  331. function get_x(int32 t) public returns (int32) {
  332. return x * t;
  333. }
  334. }"##,
  335. Target::Substrate {
  336. address_length: 32,
  337. value_length: 16,
  338. },
  339. );
  340. assert_eq!(
  341. first_error(ns.diagnostics),
  342. "duplicate argument with name ‘t’"
  343. );
  344. let ns = parse_and_resolve(
  345. r##"
  346. contract c {
  347. b x;
  348. constructor() public {
  349. x = new b({ a: 1, a: 2 });
  350. }
  351. function test() public returns (int32) {
  352. return x.get_x({ t: 10 });
  353. }
  354. }
  355. contract b {
  356. int32 x;
  357. constructor(int32 a) public {
  358. x = a;
  359. }
  360. function get_x(int32 t) public returns (int32) {
  361. return x * t;
  362. }
  363. }"##,
  364. Target::Substrate {
  365. address_length: 32,
  366. value_length: 16,
  367. },
  368. );
  369. assert_eq!(first_error(ns.diagnostics), "duplicate argument name ‘a’");
  370. #[derive(Debug, PartialEq, Encode, Decode)]
  371. struct Ret(u32);
  372. let mut runtime = build_solidity(
  373. r##"
  374. contract c {
  375. b x;
  376. constructor() public {
  377. x = new b(102);
  378. }
  379. function test() public returns (int32) {
  380. return x.get_x({ t: 10 });
  381. }
  382. }
  383. contract b {
  384. int32 x;
  385. constructor(int32 a) public {
  386. x = a;
  387. }
  388. function get_x(int32 t) public returns (int32) {
  389. return x * t;
  390. }
  391. }"##,
  392. );
  393. runtime.constructor(0, Vec::new());
  394. runtime.function("test", Vec::new());
  395. assert_eq!(runtime.vm.output, Ret(1020).encode());
  396. }
  397. #[test]
  398. fn revert_external_call() {
  399. let mut runtime = build_solidity(
  400. r##"
  401. contract c {
  402. b x;
  403. constructor() public {
  404. x = new b(102);
  405. }
  406. function test() public returns (int32) {
  407. return x.get_x({ t: 10 });
  408. }
  409. }
  410. contract b {
  411. int32 x;
  412. constructor(int32 a) public {
  413. x = a;
  414. }
  415. function get_x(int32 t) public returns (int32) {
  416. revert("The reason why");
  417. }
  418. }"##,
  419. );
  420. runtime.constructor(0, Vec::new());
  421. runtime.function_expect_failure("test", Vec::new());
  422. }
  423. #[test]
  424. fn revert_constructor() {
  425. let mut runtime = build_solidity(
  426. r##"
  427. contract c {
  428. b x;
  429. constructor() public {
  430. }
  431. function test() public returns (int32) {
  432. x = new b(102);
  433. return x.get_x({ t: 10 });
  434. }
  435. }
  436. contract b {
  437. int32 x;
  438. constructor(int32 a) public {
  439. require(a == 0, "Hello,\
  440. World!");
  441. }
  442. function get_x(int32 t) public returns (int32) {
  443. return x * t;
  444. }
  445. }"##,
  446. );
  447. runtime.constructor(0, Vec::new());
  448. runtime.function_expect_failure("test", Vec::new());
  449. assert_eq!(runtime.vm.output.len(), 0);
  450. }
  451. #[test]
  452. fn external_datatypes() {
  453. #[derive(Debug, PartialEq, Encode, Decode)]
  454. struct Ret(u64);
  455. let mut runtime = build_solidity(
  456. r##"
  457. contract c {
  458. b x;
  459. constructor() public {
  460. x = new b(102);
  461. }
  462. function test() public returns (int64) {
  463. strukt k = x.get_x(10, "foobar", true, strukt({ f1: "abcd", f2: address(555555), f3: -1 }));
  464. assert(k.f1 == "1234");
  465. assert(k.f2 == address(102));
  466. return int64(k.f3);
  467. }
  468. }
  469. contract b {
  470. int x;
  471. constructor(int a) public {
  472. x = a;
  473. }
  474. function get_x(int t, string s, bool y, strukt k) public returns (strukt) {
  475. assert(y == true);
  476. assert(t == 10);
  477. assert(s == "foobar");
  478. assert(k.f1 == "abcd");
  479. return strukt({ f1: "1234", f2: address(102), f3: x * t });
  480. }
  481. }
  482. struct strukt {
  483. bytes4 f1;
  484. address f2;
  485. int f3;
  486. }"##,
  487. );
  488. runtime.constructor(0, Vec::new());
  489. runtime.function("test", Vec::new());
  490. assert_eq!(runtime.vm.output, Ret(1020).encode());
  491. }
  492. #[test]
  493. fn creation_code() {
  494. let ns = parse_and_resolve(
  495. r##"
  496. contract a {
  497. function test() public {
  498. bytes code = type(b).creationCode;
  499. }
  500. }
  501. contract b {
  502. int x;
  503. function test() public {
  504. a f = new a();
  505. }
  506. }
  507. "##,
  508. Target::Substrate {
  509. address_length: 32,
  510. value_length: 16,
  511. },
  512. );
  513. assert_eq!(
  514. first_error(ns.diagnostics),
  515. "circular reference creating contract ‘a’"
  516. );
  517. let ns = parse_and_resolve(
  518. r##"
  519. contract a {
  520. function test() public {
  521. bytes code = type(a).runtimeCode;
  522. }
  523. }"##,
  524. Target::Substrate {
  525. address_length: 32,
  526. value_length: 16,
  527. },
  528. );
  529. assert_eq!(
  530. first_error(ns.diagnostics),
  531. "containing our own contract code for ‘a’ would generate infinite size contract"
  532. );
  533. let mut runtime = build_solidity(
  534. r##"
  535. contract c {
  536. function test() public returns (bytes) {
  537. bytes runtime = type(b).runtimeCode;
  538. assert(runtime[0] == 0);
  539. assert(runtime[1] == 0x61); // a
  540. assert(runtime[2] == 0x73); // s
  541. assert(runtime[3] == 0x6d); // m
  542. bytes creation = type(b).creationCode;
  543. // on Substrate, they are the same
  544. assert(creation == runtime);
  545. return creation;
  546. }
  547. }
  548. contract b {
  549. int x;
  550. constructor(int a) public {
  551. x = a;
  552. }
  553. }"##,
  554. );
  555. runtime.constructor(0, Vec::new());
  556. runtime.function("test", Vec::new());
  557. #[derive(Debug, PartialEq, Encode, Decode)]
  558. struct Ret(Vec<u8>);
  559. // return value should be the code for the second contract
  560. assert_eq!(
  561. runtime.vm.output,
  562. Ret(runtime.contracts[1].0.clone()).encode()
  563. );
  564. }