variables.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. use crate::{build_solidity, first_error, no_errors, parse_and_resolve};
  2. use solang::Target;
  3. #[test]
  4. fn variable_size() {
  5. let ns = parse_and_resolve(
  6. "contract x {
  7. function foo(int[12131231313213] memory y) public {}
  8. }
  9. ",
  10. Target::Substrate {
  11. address_length: 32,
  12. value_length: 16,
  13. },
  14. );
  15. assert_eq!(
  16. first_error(ns.diagnostics),
  17. "type is too large to fit into memory"
  18. );
  19. let ns = parse_and_resolve(
  20. "contract x {
  21. function foo() public returns (int[12131231313213] memory y) {}
  22. }
  23. ",
  24. Target::Substrate {
  25. address_length: 32,
  26. value_length: 16,
  27. },
  28. );
  29. assert_eq!(
  30. first_error(ns.diagnostics),
  31. "type is too large to fit into memory"
  32. );
  33. let ns = parse_and_resolve(
  34. "contract x {
  35. function foo() public {
  36. int[64*1024] memory y;
  37. }
  38. }
  39. ",
  40. Target::Substrate {
  41. address_length: 32,
  42. value_length: 16,
  43. },
  44. );
  45. assert_eq!(
  46. first_error(ns.diagnostics),
  47. "type is too large to fit into memory"
  48. );
  49. }
  50. #[test]
  51. fn immutable() {
  52. let ns = parse_and_resolve(
  53. "contract x {
  54. int public immutable y = 1;
  55. function foo() public {
  56. y = 2;
  57. }
  58. }
  59. ",
  60. Target::Substrate {
  61. address_length: 32,
  62. value_length: 16,
  63. },
  64. );
  65. assert_eq!(
  66. first_error(ns.diagnostics),
  67. "cannot assign to immutable ‘y’ outside of constructor"
  68. );
  69. let ns = parse_and_resolve(
  70. "contract x {
  71. int public immutable y = 1;
  72. function foo() public {
  73. y += 1;
  74. }
  75. }
  76. ",
  77. Target::Substrate {
  78. address_length: 32,
  79. value_length: 16,
  80. },
  81. );
  82. assert_eq!(
  83. first_error(ns.diagnostics),
  84. "cannot assign to immutable outside of constructor"
  85. );
  86. let ns = parse_and_resolve(
  87. "contract x {
  88. int public immutable y = 1;
  89. function foo() public {
  90. y++;
  91. }
  92. }
  93. ",
  94. Target::Substrate {
  95. address_length: 32,
  96. value_length: 16,
  97. },
  98. );
  99. assert_eq!(
  100. first_error(ns.diagnostics),
  101. "cannot assign to immutable outside of constructor"
  102. );
  103. let ns = parse_and_resolve(
  104. "contract x {
  105. int[] public immutable y;
  106. function foo() public {
  107. y.push();
  108. }
  109. }
  110. ",
  111. Target::Substrate {
  112. address_length: 32,
  113. value_length: 16,
  114. },
  115. );
  116. assert_eq!(
  117. first_error(ns.diagnostics),
  118. "cannot call method on immutable array outside of constructor"
  119. );
  120. let ns = parse_and_resolve(
  121. "contract x {
  122. int public immutable y;
  123. function foo() public {
  124. int a;
  125. (y, a) = (1, 2);
  126. }
  127. }
  128. ",
  129. Target::Substrate {
  130. address_length: 32,
  131. value_length: 16,
  132. },
  133. );
  134. assert_eq!(
  135. first_error(ns.diagnostics),
  136. "cannot assign to immutable ‘y’ outside of constructor"
  137. );
  138. let ns = parse_and_resolve(
  139. "contract x {
  140. int immutable public immutable y = 1;
  141. }
  142. ",
  143. Target::Substrate {
  144. address_length: 32,
  145. value_length: 16,
  146. },
  147. );
  148. assert_eq!(
  149. first_error(ns.diagnostics),
  150. "duplicate ‘immutable’ attribute"
  151. );
  152. }
  153. #[test]
  154. fn override_attribute() {
  155. let ns = parse_and_resolve(
  156. "contract x {
  157. int override y = 1;
  158. }
  159. ",
  160. Target::Substrate {
  161. address_length: 32,
  162. value_length: 16,
  163. },
  164. );
  165. assert_eq!(
  166. first_error(ns.diagnostics),
  167. "only public variable can be declared ‘override’"
  168. );
  169. let ns = parse_and_resolve(
  170. "contract x {
  171. int override internal y = 1;
  172. }
  173. ",
  174. Target::Substrate {
  175. address_length: 32,
  176. value_length: 16,
  177. },
  178. );
  179. assert_eq!(
  180. first_error(ns.diagnostics),
  181. "only public variable can be declared ‘override’"
  182. );
  183. let ns = parse_and_resolve(
  184. "contract x {
  185. int override private y = 1;
  186. }
  187. ",
  188. Target::Substrate {
  189. address_length: 32,
  190. value_length: 16,
  191. },
  192. );
  193. assert_eq!(
  194. first_error(ns.diagnostics),
  195. "only public variable can be declared ‘override’"
  196. );
  197. let ns = parse_and_resolve(
  198. "contract x {
  199. int override override y = 1;
  200. }
  201. ",
  202. Target::Substrate {
  203. address_length: 32,
  204. value_length: 16,
  205. },
  206. );
  207. assert_eq!(
  208. first_error(ns.diagnostics),
  209. "duplicate ‘override’ attribute"
  210. );
  211. let ns = parse_and_resolve(
  212. "contract x is y {
  213. int public foo;
  214. }
  215. contract y {
  216. function foo() public virtual returns (int) {
  217. return 102;
  218. }
  219. }
  220. ",
  221. Target::Substrate {
  222. address_length: 32,
  223. value_length: 16,
  224. },
  225. );
  226. assert_eq!(
  227. first_error(ns.diagnostics),
  228. "function ‘foo’ with this signature already defined"
  229. );
  230. let ns = parse_and_resolve(
  231. "contract x is y {
  232. int public override foo;
  233. }
  234. contract y {
  235. function foo() public virtual returns (int) {
  236. return 102;
  237. }
  238. }
  239. ",
  240. Target::Substrate {
  241. address_length: 32,
  242. value_length: 16,
  243. },
  244. );
  245. no_errors(ns.diagnostics);
  246. }
  247. #[test]
  248. fn test_variable_errors() {
  249. let ns = parse_and_resolve(
  250. "contract test {
  251. // solc 0.4.25 compiles this to 30.
  252. function foo() public pure returns (int32) {
  253. int32 a = b + 3;
  254. int32 b = a + 7;
  255. return a * b;
  256. }
  257. }",
  258. Target::Substrate {
  259. address_length: 32,
  260. value_length: 16,
  261. },
  262. );
  263. assert_eq!(first_error(ns.diagnostics), "`b' is not found");
  264. }
  265. #[test]
  266. fn test_variable_initializer_errors() {
  267. // cannot read contract storage in constant
  268. let ns = parse_and_resolve(
  269. "contract test {
  270. uint x = 102;
  271. uint constant y = x + 5;
  272. }",
  273. Target::Substrate {
  274. address_length: 32,
  275. value_length: 16,
  276. },
  277. );
  278. assert_eq!(
  279. first_error(ns.diagnostics),
  280. "cannot read contract variable ‘x’ in constant expression"
  281. );
  282. // cannot read contract storage in constant
  283. let ns = parse_and_resolve(
  284. "contract test {
  285. function foo() public pure returns (uint) {
  286. return 102;
  287. }
  288. uint constant y = foo() + 5;
  289. }",
  290. Target::Substrate {
  291. address_length: 32,
  292. value_length: 16,
  293. },
  294. );
  295. assert_eq!(
  296. first_error(ns.diagnostics),
  297. "cannot call function in constant expression"
  298. );
  299. // cannot refer to variable declared later
  300. let ns = parse_and_resolve(
  301. "contract test {
  302. uint x = y + 102;
  303. uint y = 102;
  304. }",
  305. Target::Substrate {
  306. address_length: 32,
  307. value_length: 16,
  308. },
  309. );
  310. assert_eq!(first_error(ns.diagnostics), "`y' is not found");
  311. // cannot refer to variable declared later (constant)
  312. let ns = parse_and_resolve(
  313. "contract test {
  314. uint x = y + 102;
  315. uint constant y = 102;
  316. }",
  317. Target::Substrate {
  318. address_length: 32,
  319. value_length: 16,
  320. },
  321. );
  322. assert_eq!(first_error(ns.diagnostics), "`y' is not found");
  323. // cannot refer to yourself
  324. let ns = parse_and_resolve(
  325. "contract test {
  326. uint x = x + 102;
  327. }",
  328. Target::Substrate {
  329. address_length: 32,
  330. value_length: 16,
  331. },
  332. );
  333. assert_eq!(first_error(ns.diagnostics), "`x' is not found");
  334. }
  335. #[test]
  336. fn global_constants() {
  337. let ns = parse_and_resolve(
  338. "uint x = 102;",
  339. Target::Substrate {
  340. address_length: 32,
  341. value_length: 16,
  342. },
  343. );
  344. assert_eq!(
  345. first_error(ns.diagnostics),
  346. "global variable must be constant"
  347. );
  348. let ns = parse_and_resolve(
  349. "uint constant public x = 102;",
  350. Target::Substrate {
  351. address_length: 32,
  352. value_length: 16,
  353. },
  354. );
  355. assert_eq!(
  356. first_error(ns.diagnostics),
  357. "‘public’: global variable cannot have visibility specifier"
  358. );
  359. let ns = parse_and_resolve(
  360. "uint constant external x = 102;",
  361. Target::Substrate {
  362. address_length: 32,
  363. value_length: 16,
  364. },
  365. );
  366. assert_eq!(
  367. first_error(ns.diagnostics),
  368. "‘external’: global variable cannot have visibility specifier"
  369. );
  370. let ns = parse_and_resolve(
  371. "uint constant x;",
  372. Target::Substrate {
  373. address_length: 32,
  374. value_length: 16,
  375. },
  376. );
  377. assert_eq!(
  378. first_error(ns.diagnostics),
  379. "missing initializer for constant"
  380. );
  381. let ns = parse_and_resolve(
  382. "uint constant test = 5; contract test {}",
  383. Target::Substrate {
  384. address_length: 32,
  385. value_length: 16,
  386. },
  387. );
  388. assert_eq!(
  389. first_error(ns.diagnostics),
  390. "test is already defined as a contract name"
  391. );
  392. let mut runtime = build_solidity(
  393. r##"
  394. int32 constant foo = 102 + 104;
  395. contract a {
  396. function test() public payable {
  397. assert(foo == 206);
  398. }
  399. }"##,
  400. );
  401. runtime.constructor(0, Vec::new());
  402. runtime.function("test", Vec::new());
  403. let mut runtime = build_solidity(
  404. r##"
  405. string constant foo = "FOO";
  406. contract a {
  407. function test() public payable {
  408. assert(foo == "FOO");
  409. }
  410. }"##,
  411. );
  412. runtime.constructor(0, Vec::new());
  413. runtime.function("test", Vec::new());
  414. }