contracts.rs 14 KB

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