simple.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::{build_solidity, BorshToken};
  3. use num_bigint::BigInt;
  4. use solang::{file_resolver::FileResolver, Target};
  5. use std::ffi::OsStr;
  6. #[test]
  7. fn simple() {
  8. let mut vm = build_solidity(
  9. r#"
  10. contract foo {
  11. constructor() {
  12. print("Hello from constructor");
  13. }
  14. function test() public {
  15. print("Hello from function");
  16. }
  17. }"#,
  18. );
  19. vm.constructor(&[]);
  20. assert_eq!(vm.logs, "Hello from constructor");
  21. vm.logs.truncate(0);
  22. vm.function("test", &[]);
  23. assert_eq!(vm.logs, "Hello from function");
  24. }
  25. #[test]
  26. fn format() {
  27. let mut vm = build_solidity(
  28. r#"
  29. contract foo {
  30. constructor() {
  31. int x = 21847450052839212624230656502990235142567050104912751880812823948662932355201;
  32. print("x = {}".format(x));
  33. }
  34. }"#,
  35. );
  36. vm.constructor(&[]);
  37. assert_eq!(
  38. vm.logs,
  39. "x = 21847450052839212624230656502990235142567050104912751880812823948662932355201"
  40. );
  41. }
  42. #[test]
  43. fn parameters() {
  44. let mut vm = build_solidity(
  45. r#"
  46. contract foo {
  47. function test(uint32 x, uint64 y) public {
  48. if (x == 10) {
  49. print("x is 10");
  50. }
  51. if (y == 102) {
  52. print("y is 102");
  53. }
  54. }
  55. }"#,
  56. );
  57. vm.constructor(&[]);
  58. vm.function(
  59. "test",
  60. &[
  61. BorshToken::Uint {
  62. width: 32,
  63. value: BigInt::from(10u8),
  64. },
  65. BorshToken::Uint {
  66. width: 64,
  67. value: BigInt::from(10u8),
  68. },
  69. ],
  70. );
  71. assert_eq!(vm.logs, "x is 10");
  72. vm.logs.truncate(0);
  73. vm.function(
  74. "test",
  75. &[
  76. BorshToken::Uint {
  77. width: 32,
  78. value: BigInt::from(99u8),
  79. },
  80. BorshToken::Uint {
  81. width: 64,
  82. value: BigInt::from(102u8),
  83. },
  84. ],
  85. );
  86. assert_eq!(vm.logs, "y is 102");
  87. }
  88. #[test]
  89. fn returns() {
  90. let mut vm = build_solidity(
  91. r#"
  92. contract foo {
  93. function test(uint32 x) public returns (uint32) {
  94. return x * x;
  95. }
  96. }"#,
  97. );
  98. vm.constructor(&[]);
  99. let returns = vm
  100. .function(
  101. "test",
  102. &[BorshToken::Uint {
  103. width: 32,
  104. value: BigInt::from(10u8),
  105. }],
  106. )
  107. .unwrap();
  108. assert_eq!(
  109. returns,
  110. BorshToken::Uint {
  111. width: 32,
  112. value: BigInt::from(100u8)
  113. }
  114. );
  115. let mut vm = build_solidity(
  116. r#"
  117. contract foo {
  118. function test(uint64 x) public returns (bool, uint64) {
  119. return (true, x * 961748941);
  120. }
  121. }"#,
  122. );
  123. vm.constructor(&[]);
  124. let returns = vm
  125. .function(
  126. "test",
  127. &[BorshToken::Uint {
  128. width: 64,
  129. value: BigInt::from(982451653u64),
  130. }],
  131. )
  132. .unwrap()
  133. .unwrap_tuple();
  134. assert_eq!(
  135. returns,
  136. vec![
  137. BorshToken::Bool(true),
  138. BorshToken::Uint {
  139. width: 64,
  140. value: BigInt::from(961748941u64 * 982451653u64)
  141. },
  142. ]
  143. );
  144. }
  145. #[test]
  146. fn flipper() {
  147. let mut vm = build_solidity(
  148. r#"
  149. contract flipper {
  150. bool private value;
  151. /// Constructor that initializes the `bool` value to the given `init_value`.
  152. constructor(bool initvalue) {
  153. value = initvalue;
  154. }
  155. /// A message that can be called on instantiated contracts.
  156. /// This one flips the value of the stored `bool` from `true`
  157. /// to `false` and vice versa.
  158. function flip() public {
  159. value = !value;
  160. }
  161. /// Simply returns the current value of our `bool`.
  162. function get() public view returns (bool) {
  163. return value;
  164. }
  165. }"#,
  166. );
  167. vm.constructor(&[BorshToken::Bool(true)]);
  168. assert_eq!(
  169. vm.data()[0..17].to_vec(),
  170. hex::decode("6fc90ec500000000000000001800000001").unwrap()
  171. );
  172. let returns = vm.function("get", &[]).unwrap();
  173. assert_eq!(returns, BorshToken::Bool(true));
  174. vm.function("flip", &[]);
  175. assert_eq!(
  176. vm.data()[0..17].to_vec(),
  177. hex::decode("6fc90ec500000000000000001800000000").unwrap()
  178. );
  179. let returns = vm.function("get", &[]).unwrap();
  180. assert_eq!(returns, BorshToken::Bool(false));
  181. }
  182. #[test]
  183. fn incrementer() {
  184. let mut vm = build_solidity(
  185. r#"
  186. contract foo {
  187. // make sure incrementer has a base contract with an empty constructor
  188. // is to check that the correct constructor is selected at emit time
  189. // https://github.com/hyperledger/solang/issues/487
  190. constructor() {}
  191. }
  192. contract incrementer is foo {
  193. uint32 private value;
  194. /// Constructor that initializes the `int32` value to the given `init_value`.
  195. constructor(uint32 initvalue) {
  196. value = initvalue;
  197. }
  198. /// This increments the value by `by`.
  199. function inc(uint32 by) public {
  200. value += by;
  201. }
  202. /// Simply returns the current value of our `uint32`.
  203. function get() public view returns (uint32) {
  204. return value;
  205. }
  206. }"#,
  207. );
  208. vm.constructor(&[BorshToken::Uint {
  209. width: 32,
  210. value: BigInt::from(5u8),
  211. }]);
  212. let returns = vm.function("get", &[]).unwrap();
  213. assert_eq!(
  214. returns,
  215. BorshToken::Uint {
  216. width: 32,
  217. value: BigInt::from(5u8),
  218. }
  219. );
  220. vm.function(
  221. "inc",
  222. &[BorshToken::Uint {
  223. width: 32,
  224. value: BigInt::from(5u8),
  225. }],
  226. );
  227. let returns = vm.function("get", &[]).unwrap();
  228. assert_eq!(
  229. returns,
  230. BorshToken::Uint {
  231. width: 32,
  232. value: BigInt::from(10u8),
  233. }
  234. );
  235. }
  236. #[test]
  237. fn infinite_loop() {
  238. let mut cache = FileResolver::new();
  239. let src = String::from(
  240. r#"
  241. contract line {
  242. function foo() public {
  243. address x = int32(1);
  244. }
  245. }"#,
  246. );
  247. cache.set_file_contents("test.sol", src);
  248. let ns = solang::parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::Solana);
  249. ns.print_diagnostics_in_plain(&cache, false);
  250. assert_eq!(
  251. ns.diagnostics.iter().nth(1).unwrap().message,
  252. "implicit conversion from int to address not allowed"
  253. );
  254. }
  255. #[test]
  256. fn two_arrays() {
  257. let mut vm = build_solidity(
  258. r#"
  259. contract two_arrays {
  260. uint[] array1;
  261. uint[] array2;
  262. constructor() {
  263. for(uint i = 0; i < 10; i++) {
  264. unchecked {
  265. array1.push((i*uint(sha256("i"))));
  266. array2.push(((i+1)*uint(sha256("i"))));
  267. }
  268. }
  269. }
  270. }"#,
  271. );
  272. vm.constructor(&[]);
  273. }
  274. #[test]
  275. fn dead_storage_bug() {
  276. let mut vm = build_solidity(
  277. r#"
  278. contract deadstorage {
  279. uint public maxlen = 10000;
  280. uint public z;
  281. uint public v;
  282. constructor() {
  283. for(uint i = 0; i < 10; i++) {
  284. uint x = i*(10e34+9999);
  285. print("x:{}".format(x));
  286. v = x%maxlen;
  287. print("v:{}".format(v));
  288. z = v%maxlen;
  289. print("z:{}".format(z));
  290. }
  291. }
  292. }"#,
  293. );
  294. vm.constructor(&[]);
  295. let returns = vm.function("v", &[]).unwrap();
  296. assert_eq!(
  297. returns,
  298. BorshToken::Uint {
  299. width: 256,
  300. value: BigInt::from(9991u16)
  301. }
  302. );
  303. }
  304. #[test]
  305. fn simple_loops() {
  306. let mut runtime = build_solidity(
  307. r##"
  308. contract test3 {
  309. function foo(uint32 a) public returns (uint32) {
  310. uint32 b = 50 - a;
  311. uint32 c;
  312. c = 100 * b;
  313. c += 5;
  314. return a * 1000 + c;
  315. }
  316. function bar(uint32 b, bool x) public returns (uint32) {
  317. unchecked {
  318. uint32 i = 1;
  319. if (x) {
  320. do {
  321. i += 10;
  322. }
  323. while (b-- > 0);
  324. } else {
  325. uint32 j;
  326. for (j=2; j<10; j++) {
  327. i *= 3;
  328. }
  329. }
  330. return i;
  331. }
  332. }
  333. function baz(uint32 x) public returns (uint32) {
  334. for (uint32 i = 0; i<100; i++) {
  335. x *= 7;
  336. if (x > 200) {
  337. break;
  338. }
  339. x++;
  340. }
  341. return x;
  342. }
  343. }"##,
  344. );
  345. // call constructor
  346. runtime.constructor(&[]);
  347. for i in 0..=50 {
  348. let res = ((50 - i) * 100 + 5) + i * 1000;
  349. let returns = runtime
  350. .function(
  351. "foo",
  352. &[BorshToken::Uint {
  353. width: 32,
  354. value: BigInt::from(i),
  355. }],
  356. )
  357. .unwrap();
  358. assert_eq!(
  359. returns,
  360. BorshToken::Uint {
  361. width: 32,
  362. value: BigInt::from(res)
  363. }
  364. );
  365. }
  366. for i in 0..=50 {
  367. let res = (i + 1) * 10 + 1;
  368. let returns = runtime
  369. .function(
  370. "bar",
  371. &[
  372. BorshToken::Uint {
  373. width: 32,
  374. value: BigInt::from(i),
  375. },
  376. BorshToken::Bool(true),
  377. ],
  378. )
  379. .unwrap();
  380. assert_eq!(
  381. returns,
  382. BorshToken::Uint {
  383. width: 32,
  384. value: BigInt::from(res)
  385. }
  386. );
  387. }
  388. for i in 0..=50 {
  389. let mut res = 1;
  390. for _ in 2..10 {
  391. res *= 3;
  392. }
  393. let returns = runtime
  394. .function(
  395. "bar",
  396. &[
  397. BorshToken::Uint {
  398. width: 32,
  399. value: BigInt::from(i),
  400. },
  401. BorshToken::Bool(false),
  402. ],
  403. )
  404. .unwrap();
  405. assert_eq!(
  406. returns,
  407. BorshToken::Uint {
  408. width: 32,
  409. value: BigInt::from(res)
  410. }
  411. );
  412. }
  413. for i in 1..=50 {
  414. let mut res = i;
  415. for _ in 0..100 {
  416. res *= 7;
  417. if res > 200 {
  418. break;
  419. }
  420. res += 1;
  421. }
  422. let returns = runtime
  423. .function(
  424. "baz",
  425. &[BorshToken::Uint {
  426. width: 32,
  427. value: BigInt::from(i),
  428. }],
  429. )
  430. .unwrap();
  431. assert_eq!(
  432. returns,
  433. BorshToken::Uint {
  434. width: 32,
  435. value: BigInt::from(res)
  436. }
  437. );
  438. }
  439. }