simple.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::build_solidity;
  3. use ethabi::{ethereum_types::U256, Token};
  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("foo", &[]);
  20. assert_eq!(vm.logs, "Hello from constructor");
  21. vm.logs.truncate(0);
  22. vm.function("test", &[], &[], None);
  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("foo", &[]);
  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("foo", &[]);
  58. vm.function(
  59. "test",
  60. &[Token::Uint(U256::from(10)), Token::Uint(U256::from(10))],
  61. &[],
  62. None,
  63. );
  64. assert_eq!(vm.logs, "x is 10");
  65. vm.logs.truncate(0);
  66. vm.function(
  67. "test",
  68. &[Token::Uint(U256::from(99)), Token::Uint(U256::from(102))],
  69. &[],
  70. None,
  71. );
  72. assert_eq!(vm.logs, "y is 102");
  73. }
  74. #[test]
  75. fn returns() {
  76. let mut vm = build_solidity(
  77. r#"
  78. contract foo {
  79. function test(uint32 x) public returns (uint32) {
  80. return x * x;
  81. }
  82. }"#,
  83. );
  84. vm.constructor("foo", &[]);
  85. let returns = vm.function("test", &[Token::Uint(U256::from(10))], &[], None);
  86. assert_eq!(returns, vec![Token::Uint(U256::from(100))]);
  87. let mut vm = build_solidity(
  88. r#"
  89. contract foo {
  90. function test(uint64 x) public returns (bool, uint64) {
  91. return (true, x * 961748941);
  92. }
  93. }"#,
  94. );
  95. vm.constructor("foo", &[]);
  96. let returns = vm.function("test", &[Token::Uint(U256::from(982451653))], &[], None);
  97. assert_eq!(
  98. returns,
  99. vec![
  100. Token::Bool(true),
  101. Token::Uint(U256::from(961748941u64 * 982451653u64))
  102. ]
  103. );
  104. }
  105. #[test]
  106. fn flipper() {
  107. let mut vm = build_solidity(
  108. r#"
  109. contract flipper {
  110. bool private value;
  111. /// Constructor that initializes the `bool` value to the given `init_value`.
  112. constructor(bool initvalue) {
  113. value = initvalue;
  114. }
  115. /// A message that can be called on instantiated contracts.
  116. /// This one flips the value of the stored `bool` from `true`
  117. /// to `false` and vice versa.
  118. function flip() public {
  119. value = !value;
  120. }
  121. /// Simply returns the current value of our `bool`.
  122. function get() public view returns (bool) {
  123. return value;
  124. }
  125. }"#,
  126. );
  127. vm.constructor("flipper", &[Token::Bool(true)]);
  128. assert_eq!(
  129. vm.data()[0..17].to_vec(),
  130. hex::decode("6fc90ec500000000000000001800000001").unwrap()
  131. );
  132. let returns = vm.function("get", &[], &[], None);
  133. assert_eq!(returns, vec![Token::Bool(true)]);
  134. vm.function("flip", &[], &[], None);
  135. assert_eq!(
  136. vm.data()[0..17].to_vec(),
  137. hex::decode("6fc90ec500000000000000001800000000").unwrap()
  138. );
  139. let returns = vm.function("get", &[], &[], None);
  140. assert_eq!(returns, vec![Token::Bool(false)]);
  141. }
  142. #[test]
  143. fn incrementer() {
  144. let mut vm = build_solidity(
  145. r#"
  146. contract foo {
  147. // make sure incrementer has a base contract with an empty constructor
  148. // is to check that the correct constructor is selected at emit time
  149. // https://github.com/hyperledger/solang/issues/487
  150. constructor() {}
  151. }
  152. contract incrementer is foo {
  153. uint32 private value;
  154. /// Constructor that initializes the `int32` value to the given `init_value`.
  155. constructor(uint32 initvalue) {
  156. value = initvalue;
  157. }
  158. /// This increments the value by `by`.
  159. function inc(uint32 by) public {
  160. value += by;
  161. }
  162. /// Simply returns the current value of our `uint32`.
  163. function get() public view returns (uint32) {
  164. return value;
  165. }
  166. }"#,
  167. );
  168. vm.constructor("incrementer", &[Token::Uint(U256::from(5))]);
  169. let returns = vm.function("get", &[], &[], None);
  170. assert_eq!(returns, vec![Token::Uint(U256::from(5))]);
  171. vm.function("inc", &[Token::Uint(U256::from(7))], &[], None);
  172. let returns = vm.function("get", &[], &[], None);
  173. assert_eq!(returns, vec![Token::Uint(U256::from(12))]);
  174. }
  175. #[test]
  176. fn infinite_loop() {
  177. let mut cache = FileResolver::new();
  178. let src = String::from(
  179. r#"
  180. contract line {
  181. function foo() public {
  182. address x = int32(1);
  183. }
  184. }"#,
  185. );
  186. cache.set_file_contents("test.sol", src);
  187. let ns = solang::parse_and_resolve(OsStr::new("test.sol"), &mut cache, Target::Solana);
  188. ns.print_diagnostics_in_plain(&cache, false);
  189. assert_eq!(
  190. ns.diagnostics.iter().nth(1).unwrap().message,
  191. "implicit conversion from int to address not allowed"
  192. );
  193. }
  194. #[test]
  195. fn two_arrays() {
  196. let mut vm = build_solidity(
  197. r#"
  198. contract two_arrays {
  199. uint[] array1;
  200. uint[] array2;
  201. constructor() {
  202. for(uint i = 0; i < 10; i++) {
  203. unchecked {
  204. array1.push((i*uint(sha256("i"))));
  205. array2.push(((i+1)*uint(sha256("i"))));
  206. }
  207. }
  208. }
  209. }"#,
  210. );
  211. vm.constructor("two_arrays", &[]);
  212. }
  213. #[test]
  214. fn dead_storage_bug() {
  215. let mut vm = build_solidity(
  216. r#"
  217. contract deadstorage {
  218. uint public maxlen = 10000;
  219. uint public z;
  220. uint public v;
  221. constructor() {
  222. for(uint i = 0; i < 10; i++) {
  223. uint x = i*(10e34+9999);
  224. print("x:{}".format(x));
  225. v = x%maxlen;
  226. print("v:{}".format(v));
  227. z = v%maxlen;
  228. print("z:{}".format(z));
  229. }
  230. }
  231. }"#,
  232. );
  233. vm.constructor("deadstorage", &[]);
  234. let returns = vm.function("v", &[], &[], None);
  235. assert_eq!(returns, vec![Token::Uint(U256::from(9991))]);
  236. }
  237. #[test]
  238. fn simple_loops() {
  239. let mut runtime = build_solidity(
  240. r##"
  241. contract test3 {
  242. function foo(uint32 a) public returns (uint32) {
  243. uint32 b = 50 - a;
  244. uint32 c;
  245. c = 100 * b;
  246. c += 5;
  247. return a * 1000 + c;
  248. }
  249. function bar(uint32 b, bool x) public returns (uint32) {
  250. uint32 i = 1;
  251. if (x) {
  252. do {
  253. i += 10;
  254. }
  255. while (b-- > 0);
  256. } else {
  257. uint32 j;
  258. for (j=2; j<10; j++) {
  259. i *= 3;
  260. }
  261. }
  262. return i;
  263. }
  264. function baz(uint32 x) public returns (uint32) {
  265. for (uint32 i = 0; i<100; i++) {
  266. x *= 7;
  267. if (x > 200) {
  268. break;
  269. }
  270. x++;
  271. }
  272. return x;
  273. }
  274. }"##,
  275. );
  276. // call constructor
  277. runtime.constructor("test3", &[]);
  278. for i in 0..=50 {
  279. let res = ((50 - i) * 100 + 5) + i * 1000;
  280. let returns = runtime.function("foo", &[Token::Uint(U256::from(i))], &[], None);
  281. assert_eq!(returns, vec![Token::Uint(U256::from(res))]);
  282. }
  283. for i in 0..=50 {
  284. let res = (i + 1) * 10 + 1;
  285. let returns = runtime.function(
  286. "bar",
  287. &[Token::Uint(U256::from(i)), Token::Bool(true)],
  288. &[],
  289. None,
  290. );
  291. assert_eq!(returns, vec![Token::Uint(U256::from(res))]);
  292. }
  293. for i in 0..=50 {
  294. let mut res = 1;
  295. for _ in 2..10 {
  296. res *= 3;
  297. }
  298. let returns = runtime.function(
  299. "bar",
  300. &[Token::Uint(U256::from(i)), Token::Bool(false)],
  301. &[],
  302. None,
  303. );
  304. assert_eq!(returns, vec![Token::Uint(U256::from(res))]);
  305. }
  306. for i in 1..=50 {
  307. let mut res = i;
  308. for _ in 0..100 {
  309. res *= 7;
  310. if res > 200 {
  311. break;
  312. }
  313. res += 1;
  314. }
  315. let returns = runtime.function("baz", &[Token::Uint(U256::from(i))], &[], None);
  316. assert_eq!(returns, vec![Token::Uint(U256::from(res))]);
  317. }
  318. }