arrays.rs 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::{build_solidity, BorshToken, Pubkey};
  3. use num_bigint::BigInt;
  4. use num_traits::{One, Zero};
  5. #[test]
  6. fn fixed_array() {
  7. // test that the abi encoder can handle fixed arrays
  8. let mut vm = build_solidity(
  9. r#"
  10. contract foo {
  11. function get() public returns (uint32[4] f, bytes1 g) {
  12. f[0] = 1;
  13. f[1] = 102;
  14. f[2] = 300331;
  15. f[3] = 12313231;
  16. g = 0xfe;
  17. }
  18. }"#,
  19. );
  20. let data_account = vm.initialize_data_account();
  21. vm.function("new")
  22. .accounts(vec![("dataAccount", data_account)])
  23. .call();
  24. let returns = vm.function("get").call().unwrap().unwrap_tuple();
  25. assert_eq!(
  26. returns,
  27. vec![
  28. BorshToken::FixedArray(vec![
  29. BorshToken::Uint {
  30. width: 32,
  31. value: BigInt::from(1u8),
  32. },
  33. BorshToken::Uint {
  34. width: 32,
  35. value: BigInt::from(102u8),
  36. },
  37. BorshToken::Uint {
  38. width: 32,
  39. value: BigInt::from(300331u32),
  40. },
  41. BorshToken::Uint {
  42. width: 32,
  43. value: BigInt::from(12313231u32),
  44. },
  45. ]),
  46. BorshToken::uint8_fixed_array(vec!(0xfe))
  47. ]
  48. );
  49. // let's make it more interesting. Return some structs, some of which will be null pointers
  50. // when they get to the abi encoder
  51. let mut vm = build_solidity(
  52. r#"
  53. struct X {
  54. uint32 f1;
  55. bool f2;
  56. }
  57. contract foo {
  58. function get() public returns (X[4] f) {
  59. f[1].f1 = 102;
  60. f[1].f2 = true;
  61. }
  62. }"#,
  63. );
  64. let data_account = vm.initialize_data_account();
  65. vm.function("new")
  66. .accounts(vec![("dataAccount", data_account)])
  67. .call();
  68. let returns = vm.function("get").call().unwrap();
  69. assert_eq!(
  70. returns,
  71. BorshToken::FixedArray(vec![
  72. BorshToken::Tuple(vec![
  73. BorshToken::Uint {
  74. width: 32,
  75. value: BigInt::zero(),
  76. },
  77. BorshToken::Bool(false)
  78. ]),
  79. BorshToken::Tuple(vec![
  80. BorshToken::Uint {
  81. width: 32,
  82. value: BigInt::from(102u8),
  83. },
  84. BorshToken::Bool(true)
  85. ]),
  86. BorshToken::Tuple(vec![
  87. BorshToken::Uint {
  88. width: 32,
  89. value: BigInt::zero(),
  90. },
  91. BorshToken::Bool(false)
  92. ]),
  93. BorshToken::Tuple(vec![
  94. BorshToken::Uint {
  95. width: 32,
  96. value: BigInt::zero(),
  97. },
  98. BorshToken::Bool(false)
  99. ]),
  100. ])
  101. );
  102. // Now let's try it the other way round; an struct with an array in it
  103. let mut vm = build_solidity(
  104. r#"
  105. struct X {
  106. bool f0;
  107. uint32[4] f1;
  108. bool f2;
  109. }
  110. contract foo {
  111. function get() public returns (X f) {
  112. f.f0 = true;
  113. f.f2 = true;
  114. }
  115. function set(X f) public returns (uint32) {
  116. assert(f.f0 == true);
  117. assert(f.f2 == true);
  118. uint32 sum = 0;
  119. for (uint32 i = 0; i < f.f1.length; i++) {
  120. sum += f.f1[i];
  121. }
  122. return sum;
  123. }
  124. }"#,
  125. );
  126. let data_account = vm.initialize_data_account();
  127. vm.function("new")
  128. .accounts(vec![("dataAccount", data_account)])
  129. .call();
  130. let returns = vm.function("get").call().unwrap();
  131. assert_eq!(
  132. returns,
  133. BorshToken::Tuple(vec![
  134. BorshToken::Bool(true),
  135. BorshToken::FixedArray(vec![
  136. BorshToken::Uint {
  137. width: 32,
  138. value: BigInt::zero(),
  139. },
  140. BorshToken::Uint {
  141. width: 32,
  142. value: BigInt::zero(),
  143. },
  144. BorshToken::Uint {
  145. width: 32,
  146. value: BigInt::zero(),
  147. },
  148. BorshToken::Uint {
  149. width: 32,
  150. value: BigInt::zero(),
  151. },
  152. ]),
  153. BorshToken::Bool(true)
  154. ]),
  155. );
  156. let returns = vm
  157. .function("set")
  158. .arguments(&[BorshToken::Tuple(vec![
  159. BorshToken::Bool(true),
  160. BorshToken::FixedArray(vec![
  161. BorshToken::Uint {
  162. width: 32,
  163. value: BigInt::from(3u8),
  164. },
  165. BorshToken::Uint {
  166. width: 32,
  167. value: BigInt::from(5u8),
  168. },
  169. BorshToken::Uint {
  170. width: 32,
  171. value: BigInt::from(7u8),
  172. },
  173. BorshToken::Uint {
  174. width: 32,
  175. value: BigInt::from(11u8),
  176. },
  177. ]),
  178. BorshToken::Bool(true),
  179. ])])
  180. .call()
  181. .unwrap();
  182. assert_eq!(
  183. returns,
  184. BorshToken::Uint {
  185. width: 32,
  186. value: BigInt::from(26u8),
  187. }
  188. );
  189. }
  190. #[test]
  191. fn dynamic_array_fixed_elements() {
  192. // test that the abi decoder can handle fixed arrays
  193. let mut vm = build_solidity(
  194. r#"
  195. contract foo {
  196. function get(uint x, uint32[] f, uint g) public returns (uint32) {
  197. assert(x == 12123123);
  198. assert(g == 102);
  199. uint32 sum = 0;
  200. for (uint32 i = 0; i < f.length; i++) {
  201. sum += f[i];
  202. }
  203. return sum;
  204. }
  205. function set() public returns (uint x, uint32[] f, string g) {
  206. x = 12123123;
  207. f = new uint32[](4);
  208. f[0] = 3; f[1] = 5; f[2] = 7; f[3] = 11;
  209. g = "abcd";
  210. }
  211. }"#,
  212. );
  213. let data_account = vm.initialize_data_account();
  214. vm.function("new")
  215. .accounts(vec![("dataAccount", data_account)])
  216. .call();
  217. let returns = vm
  218. .function("get")
  219. .arguments(&[
  220. BorshToken::Uint {
  221. width: 256,
  222. value: BigInt::from(12123123u32),
  223. },
  224. BorshToken::Array(vec![
  225. BorshToken::Uint {
  226. width: 32,
  227. value: BigInt::from(3u8),
  228. },
  229. BorshToken::Uint {
  230. width: 32,
  231. value: BigInt::from(5u8),
  232. },
  233. BorshToken::Uint {
  234. width: 32,
  235. value: BigInt::from(7u8),
  236. },
  237. BorshToken::Uint {
  238. width: 32,
  239. value: BigInt::from(11u8),
  240. },
  241. ]),
  242. BorshToken::Uint {
  243. width: 256,
  244. value: BigInt::from(102u8),
  245. },
  246. ])
  247. .call()
  248. .unwrap();
  249. assert_eq!(
  250. returns,
  251. BorshToken::Uint {
  252. width: 32,
  253. value: BigInt::from(26u8),
  254. }
  255. );
  256. // test that the abi encoder can handle fixed arrays
  257. let returns = vm.function("set").call().unwrap().unwrap_tuple();
  258. assert_eq!(
  259. returns,
  260. vec![
  261. BorshToken::Uint {
  262. width: 256,
  263. value: BigInt::from(12123123u32),
  264. },
  265. BorshToken::Array(vec![
  266. BorshToken::Uint {
  267. width: 32,
  268. value: BigInt::from(3u8),
  269. },
  270. BorshToken::Uint {
  271. width: 32,
  272. value: BigInt::from(5u8),
  273. },
  274. BorshToken::Uint {
  275. width: 32,
  276. value: BigInt::from(7u8),
  277. },
  278. BorshToken::Uint {
  279. width: 32,
  280. value: BigInt::from(11u8),
  281. },
  282. ]),
  283. BorshToken::String(String::from("abcd")),
  284. ]
  285. );
  286. }
  287. #[test]
  288. fn fixed_array_dynamic_elements() {
  289. // test that the abi decoder can handle fixed arrays
  290. let mut vm = build_solidity(
  291. r#"
  292. contract foo {
  293. function get(uint x, bytes[4] f, uint g) public returns (uint32) {
  294. assert(x == 12123123);
  295. assert(g == 102);
  296. uint32 sum = 0;
  297. for (uint32 i = 0; i < f.length; i++) {
  298. for (uint32 j = 0; j < f[i].length; j++)
  299. sum += f[i][j];
  300. }
  301. return sum;
  302. }
  303. function set() public returns (uint x, bytes[4] f, uint g) {
  304. x = 12123123;
  305. f[0] = hex"030507";
  306. f[1] = hex"0b0d11";
  307. f[2] = hex"1317";
  308. f[3] = hex"1d";
  309. g = 102;
  310. }
  311. }"#,
  312. );
  313. let data_account = vm.initialize_data_account();
  314. vm.function("new")
  315. .accounts(vec![("dataAccount", data_account)])
  316. .call();
  317. let returns = vm
  318. .function("get")
  319. .arguments(&[
  320. BorshToken::Uint {
  321. width: 256,
  322. value: BigInt::from(12123123u32),
  323. },
  324. BorshToken::FixedArray(vec![
  325. BorshToken::Bytes(vec![3, 5, 7]),
  326. BorshToken::Bytes(vec![11, 13, 17]),
  327. BorshToken::Bytes(vec![19, 23]),
  328. BorshToken::Bytes(vec![29]),
  329. ]),
  330. BorshToken::Uint {
  331. width: 256,
  332. value: BigInt::from(102u8),
  333. },
  334. ])
  335. .call()
  336. .unwrap();
  337. assert_eq!(
  338. returns,
  339. BorshToken::Uint {
  340. width: 32,
  341. value: BigInt::from(127),
  342. }
  343. );
  344. let returns = vm.function("set").call().unwrap().unwrap_tuple();
  345. assert_eq!(
  346. returns,
  347. vec![
  348. BorshToken::Uint {
  349. width: 256,
  350. value: BigInt::from(12123123u32)
  351. },
  352. BorshToken::FixedArray(vec![
  353. BorshToken::Bytes(vec![3, 5, 7]),
  354. BorshToken::Bytes(vec![11, 13, 17]),
  355. BorshToken::Bytes(vec![19, 23]),
  356. BorshToken::Bytes(vec![29]),
  357. ]),
  358. BorshToken::Uint {
  359. width: 256,
  360. value: BigInt::from(102u8)
  361. },
  362. ]
  363. );
  364. }
  365. #[test]
  366. fn dynamic_array_dynamic_elements() {
  367. // test that the abi decoder can handle fixed arrays
  368. let mut vm = build_solidity(
  369. r#"
  370. contract foo {
  371. function get(uint x, bytes[] f, uint g) public returns (uint32) {
  372. assert(x == 12123123);
  373. assert(g == 102);
  374. uint32 sum = 0;
  375. for (uint32 i = 0; i < f.length; i++) {
  376. for (uint32 j = 0; j < f[i].length; j++)
  377. sum += f[i][j];
  378. }
  379. return sum;
  380. }
  381. function set() public returns (uint x, bytes[] f, string g) {
  382. x = 12123123;
  383. f = new bytes[](4);
  384. f[0] = hex"030507";
  385. f[1] = hex"0b0d11";
  386. f[2] = hex"1317";
  387. f[3] = hex"1d";
  388. g = "feh";
  389. }
  390. }"#,
  391. );
  392. let data_account = vm.initialize_data_account();
  393. vm.function("new")
  394. .accounts(vec![("dataAccount", data_account)])
  395. .call();
  396. let returns = vm
  397. .function("get")
  398. .arguments(&[
  399. BorshToken::Uint {
  400. width: 256,
  401. value: BigInt::from(12123123u32),
  402. },
  403. BorshToken::Array(vec![
  404. BorshToken::Bytes(vec![3, 5, 7]),
  405. BorshToken::Bytes(vec![11, 13, 17]),
  406. BorshToken::Bytes(vec![19, 23]),
  407. BorshToken::Bytes(vec![29]),
  408. ]),
  409. BorshToken::Uint {
  410. width: 256,
  411. value: BigInt::from(102u8),
  412. },
  413. ])
  414. .call()
  415. .unwrap();
  416. assert_eq!(
  417. returns,
  418. BorshToken::Uint {
  419. width: 32,
  420. value: BigInt::from(127),
  421. }
  422. );
  423. let returns = vm.function("set").call().unwrap().unwrap_tuple();
  424. assert_eq!(
  425. returns,
  426. vec![
  427. BorshToken::Uint {
  428. width: 256,
  429. value: BigInt::from(12123123u32)
  430. },
  431. BorshToken::Array(vec![
  432. BorshToken::Bytes(vec![3, 5, 7]),
  433. BorshToken::Bytes(vec![11, 13, 17]),
  434. BorshToken::Bytes(vec![19, 23]),
  435. BorshToken::Bytes(vec![29]),
  436. ]),
  437. BorshToken::String(String::from("feh")),
  438. ]
  439. );
  440. }
  441. #[test]
  442. fn fixed_array_fixed_elements_storage() {
  443. let mut vm = build_solidity(
  444. r#"
  445. contract foo {
  446. int64[4] store;
  447. function set_elem(uint index, int64 val) public {
  448. store[index] = val;
  449. }
  450. function get_elem(uint index) public returns (int64) {
  451. return store[index];
  452. }
  453. function set(int64[4] x) public {
  454. store = x;
  455. }
  456. function get() public returns (int64[4]) {
  457. return store;
  458. }
  459. function del() public {
  460. delete store;
  461. }
  462. }"#,
  463. );
  464. let data_account = vm.initialize_data_account();
  465. vm.function("new")
  466. .accounts(vec![("dataAccount", data_account)])
  467. .call();
  468. vm.function("set_elem")
  469. .arguments(&[
  470. BorshToken::Uint {
  471. width: 256,
  472. value: BigInt::from(2u8),
  473. },
  474. BorshToken::Int {
  475. width: 64,
  476. value: BigInt::from(12123123u64),
  477. },
  478. ])
  479. .accounts(vec![("dataAccount", data_account)])
  480. .call();
  481. vm.function("set_elem")
  482. .arguments(&[
  483. BorshToken::Uint {
  484. width: 256,
  485. value: BigInt::from(3u8),
  486. },
  487. BorshToken::Uint {
  488. width: 64,
  489. value: BigInt::from(123456789u64),
  490. },
  491. ])
  492. .accounts(vec![("dataAccount", data_account)])
  493. .call();
  494. let returns = vm
  495. .function("get_elem")
  496. .arguments(&[BorshToken::Uint {
  497. width: 256,
  498. value: BigInt::from(2u8),
  499. }])
  500. .accounts(vec![("dataAccount", data_account)])
  501. .call()
  502. .unwrap();
  503. assert_eq!(
  504. returns,
  505. BorshToken::Int {
  506. width: 64,
  507. value: BigInt::from(12123123u64)
  508. },
  509. );
  510. let returns = vm
  511. .function("get")
  512. .accounts(vec![("dataAccount", data_account)])
  513. .call()
  514. .unwrap();
  515. assert_eq!(
  516. returns,
  517. BorshToken::FixedArray(vec![
  518. BorshToken::Int {
  519. width: 64,
  520. value: BigInt::zero()
  521. },
  522. BorshToken::Int {
  523. width: 64,
  524. value: BigInt::zero()
  525. },
  526. BorshToken::Int {
  527. width: 64,
  528. value: BigInt::from(12123123u32),
  529. },
  530. BorshToken::Int {
  531. width: 64,
  532. value: BigInt::from(123456789u32),
  533. },
  534. ]),
  535. );
  536. vm.function("set")
  537. .arguments(&[BorshToken::FixedArray(vec![
  538. BorshToken::Int {
  539. width: 64,
  540. value: BigInt::one(),
  541. },
  542. BorshToken::Int {
  543. width: 64,
  544. value: BigInt::from(2u8),
  545. },
  546. BorshToken::Int {
  547. width: 64,
  548. value: BigInt::from(3u8),
  549. },
  550. BorshToken::Int {
  551. width: 64,
  552. value: BigInt::from(4u8),
  553. },
  554. ])])
  555. .accounts(vec![("dataAccount", data_account)])
  556. .call();
  557. let returns = vm
  558. .function("get")
  559. .accounts(vec![("dataAccount", data_account)])
  560. .call()
  561. .unwrap();
  562. assert_eq!(
  563. returns,
  564. BorshToken::FixedArray(vec![
  565. BorshToken::Int {
  566. width: 64,
  567. value: BigInt::one(),
  568. },
  569. BorshToken::Int {
  570. width: 64,
  571. value: BigInt::from(2u8),
  572. },
  573. BorshToken::Int {
  574. width: 64,
  575. value: BigInt::from(3u8),
  576. },
  577. BorshToken::Int {
  578. width: 64,
  579. value: BigInt::from(4u8),
  580. },
  581. ]),
  582. );
  583. vm.function("del")
  584. .accounts(vec![("dataAccount", data_account)])
  585. .call();
  586. let returns = vm
  587. .function("get")
  588. .accounts(vec![("dataAccount", data_account)])
  589. .call()
  590. .unwrap();
  591. assert_eq!(
  592. returns,
  593. BorshToken::FixedArray(vec![
  594. BorshToken::Int {
  595. width: 64,
  596. value: BigInt::zero(),
  597. },
  598. BorshToken::Int {
  599. width: 64,
  600. value: BigInt::zero(),
  601. },
  602. BorshToken::Int {
  603. width: 64,
  604. value: BigInt::zero(),
  605. },
  606. BorshToken::Int {
  607. width: 64,
  608. value: BigInt::zero(),
  609. },
  610. ]),
  611. );
  612. }
  613. #[test]
  614. fn fixed_array_dynamic_elements_storage() {
  615. let mut vm = build_solidity(
  616. r#"
  617. contract foo {
  618. string[4] store;
  619. function set_elem(uint index, string val) public {
  620. store[index] = val;
  621. }
  622. function get_elem(uint index) public returns (string) {
  623. return store[index];
  624. }
  625. function set(string[4] x) public {
  626. store = x;
  627. }
  628. function get() public returns (string[4]) {
  629. return store;
  630. }
  631. function del() public {
  632. delete store;
  633. }
  634. }"#,
  635. );
  636. let data_account = vm.initialize_data_account();
  637. vm.function("new")
  638. .accounts(vec![("dataAccount", data_account)])
  639. .call();
  640. vm.function("set_elem")
  641. .arguments(&[
  642. BorshToken::Uint {
  643. width: 256,
  644. value: BigInt::from(2u8),
  645. },
  646. BorshToken::String(String::from("abcd")),
  647. ])
  648. .accounts(vec![("dataAccount", data_account)])
  649. .call();
  650. vm.function("set_elem")
  651. .arguments(&[
  652. BorshToken::Uint {
  653. width: 256,
  654. value: BigInt::from(3u8),
  655. },
  656. BorshToken::String(String::from(
  657. "you can lead a horse to water but you can’t make him drink",
  658. )),
  659. ])
  660. .accounts(vec![("dataAccount", data_account)])
  661. .call();
  662. let returns = vm
  663. .function("get_elem")
  664. .arguments(&[BorshToken::Uint {
  665. width: 256,
  666. value: BigInt::from(2u8),
  667. }])
  668. .accounts(vec![("dataAccount", data_account)])
  669. .call()
  670. .unwrap();
  671. assert_eq!(returns, BorshToken::String(String::from("abcd")));
  672. let returns = vm
  673. .function("get")
  674. .accounts(vec![("dataAccount", data_account)])
  675. .call()
  676. .unwrap();
  677. assert_eq!(
  678. returns,
  679. BorshToken::FixedArray(vec![
  680. BorshToken::String(String::from("")),
  681. BorshToken::String(String::from("")),
  682. BorshToken::String(String::from("abcd")),
  683. BorshToken::String(String::from(
  684. "you can lead a horse to water but you can’t make him drink"
  685. )),
  686. ]),
  687. );
  688. vm.function("set")
  689. .arguments(&[BorshToken::FixedArray(vec![
  690. BorshToken::String(String::from("a")),
  691. BorshToken::String(String::from("b")),
  692. BorshToken::String(String::from("c")),
  693. BorshToken::String(String::from("d")),
  694. ])])
  695. .accounts(vec![("dataAccount", data_account)])
  696. .call();
  697. let returns = vm
  698. .function("get")
  699. .accounts(vec![("dataAccount", data_account)])
  700. .call()
  701. .unwrap();
  702. assert_eq!(
  703. returns,
  704. BorshToken::FixedArray(vec![
  705. BorshToken::String(String::from("a")),
  706. BorshToken::String(String::from("b")),
  707. BorshToken::String(String::from("c")),
  708. BorshToken::String(String::from("d")),
  709. ]),
  710. );
  711. vm.function("del")
  712. .accounts(vec![("dataAccount", data_account)])
  713. .call();
  714. let returns = vm
  715. .function("get")
  716. .accounts(vec![("dataAccount", data_account)])
  717. .call()
  718. .unwrap();
  719. assert_eq!(
  720. returns,
  721. BorshToken::FixedArray(vec![
  722. BorshToken::String(String::from("")),
  723. BorshToken::String(String::from("")),
  724. BorshToken::String(String::from("")),
  725. BorshToken::String(String::from("")),
  726. ]),
  727. );
  728. }
  729. #[test]
  730. fn storage_simple_dynamic_array() {
  731. let mut vm = build_solidity(
  732. r#"
  733. contract foo {
  734. int64[] store;
  735. function push(int64 x) public {
  736. store.push(x);
  737. }
  738. function push_zero() public {
  739. store.push();
  740. }
  741. function pop() public returns (int64) {
  742. return store.pop();
  743. }
  744. function len() public returns (uint) {
  745. return store.length;
  746. }
  747. function subscript(uint32 i) public returns (int64) {
  748. return store[i];
  749. }
  750. function copy() public returns (int64[] memory) {
  751. return store;
  752. }
  753. function set(int64[] n) public {
  754. store = n;
  755. }
  756. function rm() public {
  757. delete store;
  758. }
  759. }"#,
  760. );
  761. let data_account = vm.initialize_data_account();
  762. vm.function("new")
  763. .accounts(vec![("dataAccount", data_account)])
  764. .call();
  765. let returns = vm
  766. .function("len")
  767. .accounts(vec![("dataAccount", data_account)])
  768. .call()
  769. .unwrap();
  770. assert_eq!(
  771. returns,
  772. BorshToken::Uint {
  773. width: 256,
  774. value: BigInt::zero(),
  775. }
  776. );
  777. vm.function("push")
  778. .arguments(&[BorshToken::Int {
  779. width: 64,
  780. value: BigInt::from(102u8),
  781. }])
  782. .accounts(vec![("dataAccount", data_account)])
  783. .call();
  784. vm.function("push_zero")
  785. .accounts(vec![("dataAccount", data_account)])
  786. .call();
  787. vm.function("push")
  788. .arguments(&[BorshToken::Int {
  789. width: 64,
  790. value: BigInt::from(12345678901u64),
  791. }])
  792. .accounts(vec![("dataAccount", data_account)])
  793. .call();
  794. let returns = vm
  795. .function("subscript")
  796. .arguments(&[BorshToken::Uint {
  797. width: 32,
  798. value: BigInt::zero(),
  799. }])
  800. .accounts(vec![("dataAccount", data_account)])
  801. .call()
  802. .unwrap();
  803. assert_eq!(
  804. returns,
  805. BorshToken::Int {
  806. width: 64,
  807. value: BigInt::from(102u8),
  808. }
  809. );
  810. let returns = vm
  811. .function("subscript")
  812. .arguments(&[BorshToken::Uint {
  813. width: 32,
  814. value: BigInt::one(),
  815. }])
  816. .accounts(vec![("dataAccount", data_account)])
  817. .call()
  818. .unwrap();
  819. assert_eq!(
  820. returns,
  821. BorshToken::Int {
  822. width: 64,
  823. value: BigInt::zero()
  824. }
  825. );
  826. let returns = vm
  827. .function("subscript")
  828. .arguments(&[BorshToken::Uint {
  829. width: 32,
  830. value: BigInt::from(2u8),
  831. }])
  832. .accounts(vec![("dataAccount", data_account)])
  833. .call()
  834. .unwrap();
  835. assert_eq!(
  836. returns,
  837. BorshToken::Int {
  838. width: 64,
  839. value: BigInt::from(12345678901u64),
  840. },
  841. );
  842. let returns = vm
  843. .function("copy")
  844. .accounts(vec![("dataAccount", data_account)])
  845. .call()
  846. .unwrap();
  847. assert_eq!(
  848. returns,
  849. BorshToken::Array(vec![
  850. BorshToken::Int {
  851. width: 64,
  852. value: BigInt::from(102u8),
  853. },
  854. BorshToken::Int {
  855. width: 64,
  856. value: BigInt::zero(),
  857. },
  858. BorshToken::Int {
  859. width: 64,
  860. value: BigInt::from(12345678901u64),
  861. },
  862. ]),
  863. );
  864. let returns = vm
  865. .function("pop")
  866. .accounts(vec![("dataAccount", data_account)])
  867. .call()
  868. .unwrap();
  869. assert_eq!(
  870. returns,
  871. BorshToken::Int {
  872. width: 64,
  873. value: BigInt::from(12345678901u64),
  874. },
  875. );
  876. let returns = vm
  877. .function("len")
  878. .accounts(vec![("dataAccount", data_account)])
  879. .call()
  880. .unwrap();
  881. assert_eq!(
  882. returns,
  883. BorshToken::Uint {
  884. width: 256,
  885. value: BigInt::from(2u8),
  886. }
  887. );
  888. vm.function("set")
  889. .arguments(&[BorshToken::Array(vec![
  890. BorshToken::Uint {
  891. width: 64,
  892. value: BigInt::from(1u8),
  893. },
  894. BorshToken::Uint {
  895. width: 64,
  896. value: BigInt::from(2u8),
  897. },
  898. BorshToken::Uint {
  899. width: 64,
  900. value: BigInt::from(3u8),
  901. },
  902. BorshToken::Uint {
  903. width: 64,
  904. value: BigInt::from(4u8),
  905. },
  906. BorshToken::Uint {
  907. width: 64,
  908. value: BigInt::from(5u8),
  909. },
  910. BorshToken::Uint {
  911. width: 64,
  912. value: BigInt::from(6u8),
  913. },
  914. BorshToken::Uint {
  915. width: 64,
  916. value: BigInt::from(7u8),
  917. },
  918. ])])
  919. .accounts(vec![("dataAccount", data_account)])
  920. .call();
  921. let returns = vm
  922. .function("copy")
  923. .accounts(vec![("dataAccount", data_account)])
  924. .call()
  925. .unwrap();
  926. assert_eq!(
  927. returns,
  928. BorshToken::Array(vec![
  929. BorshToken::Int {
  930. width: 64,
  931. value: BigInt::from(1u8)
  932. },
  933. BorshToken::Int {
  934. width: 64,
  935. value: BigInt::from(2u8)
  936. },
  937. BorshToken::Int {
  938. width: 64,
  939. value: BigInt::from(3u8)
  940. },
  941. BorshToken::Int {
  942. width: 64,
  943. value: BigInt::from(4u8)
  944. },
  945. BorshToken::Int {
  946. width: 64,
  947. value: BigInt::from(5u8)
  948. },
  949. BorshToken::Int {
  950. width: 64,
  951. value: BigInt::from(6u8)
  952. },
  953. BorshToken::Int {
  954. width: 64,
  955. value: BigInt::from(7u8)
  956. },
  957. ]),
  958. );
  959. vm.function("rm")
  960. .accounts(vec![("dataAccount", data_account)])
  961. .call();
  962. let returns = vm
  963. .function("len")
  964. .accounts(vec![("dataAccount", data_account)])
  965. .call()
  966. .unwrap();
  967. assert_eq!(
  968. returns,
  969. BorshToken::Uint {
  970. width: 256,
  971. value: BigInt::zero(),
  972. }
  973. );
  974. }
  975. #[test]
  976. #[should_panic]
  977. fn storage_pop_running_on_empty() {
  978. let mut vm = build_solidity(
  979. r#"
  980. contract foo {
  981. int64[] store;
  982. function pop() public returns (int64) {
  983. return store.pop();
  984. }
  985. }"#,
  986. );
  987. let data_account = vm.initialize_data_account();
  988. vm.function("new")
  989. .accounts(vec![("dataAccount", data_account)])
  990. .call();
  991. vm.function("pop")
  992. .accounts(vec![("dataAccount", data_account)])
  993. .call();
  994. }
  995. #[test]
  996. fn storage_dynamic_array_of_structs() {
  997. let mut vm = build_solidity(
  998. r#"
  999. struct S {
  1000. uint64 f1;
  1001. bool f2;
  1002. }
  1003. contract foo {
  1004. S[] store;
  1005. function push1(S x) public {
  1006. store.push(x);
  1007. }
  1008. function push2(S x) public {
  1009. S storage f = store.push();
  1010. f.f1 = x.f1;
  1011. f.f2 = x.f2;
  1012. }
  1013. function push_empty() public {
  1014. store.push();
  1015. }
  1016. function pop() public returns (S) {
  1017. return store.pop();
  1018. }
  1019. function len() public returns (uint) {
  1020. return store.length;
  1021. }
  1022. function subscript(uint32 i) public returns (S) {
  1023. return store[i];
  1024. }
  1025. function copy() public returns (S[] memory) {
  1026. return store;
  1027. }
  1028. function set(S[] memory n) public {
  1029. store = n;
  1030. }
  1031. function rm() public {
  1032. delete store;
  1033. }
  1034. }"#,
  1035. );
  1036. let data_account = vm.initialize_data_account();
  1037. vm.function("new")
  1038. .accounts(vec![("dataAccount", data_account)])
  1039. .call();
  1040. let returns = vm
  1041. .function("len")
  1042. .accounts(vec![("dataAccount", data_account)])
  1043. .call()
  1044. .unwrap();
  1045. assert_eq!(
  1046. returns,
  1047. BorshToken::Uint {
  1048. width: 256,
  1049. value: BigInt::zero(),
  1050. }
  1051. );
  1052. vm.function("push1")
  1053. .arguments(&[BorshToken::Tuple(vec![
  1054. BorshToken::Uint {
  1055. width: 64,
  1056. value: BigInt::from(13819038012u64),
  1057. },
  1058. BorshToken::Bool(true),
  1059. ])])
  1060. .accounts(vec![("dataAccount", data_account)])
  1061. .call();
  1062. vm.function("push_empty")
  1063. .accounts(vec![("dataAccount", data_account)])
  1064. .call();
  1065. vm.function("push2")
  1066. .arguments(&[BorshToken::Tuple(vec![
  1067. BorshToken::Uint {
  1068. width: 64,
  1069. value: BigInt::from(12313123141123213u64),
  1070. },
  1071. BorshToken::Bool(true),
  1072. ])])
  1073. .accounts(vec![("dataAccount", data_account)])
  1074. .call();
  1075. let returns = vm
  1076. .function("subscript")
  1077. .arguments(&[BorshToken::Uint {
  1078. width: 32,
  1079. value: BigInt::zero(),
  1080. }])
  1081. .accounts(vec![("dataAccount", data_account)])
  1082. .call()
  1083. .unwrap();
  1084. assert_eq!(
  1085. returns,
  1086. BorshToken::Tuple(vec![
  1087. BorshToken::Uint {
  1088. width: 64,
  1089. value: BigInt::from(13819038012u64)
  1090. },
  1091. BorshToken::Bool(true),
  1092. ])
  1093. );
  1094. let returns = vm
  1095. .function("subscript")
  1096. .arguments(&[BorshToken::Uint {
  1097. width: 32,
  1098. value: BigInt::one(),
  1099. }])
  1100. .accounts(vec![("dataAccount", data_account)])
  1101. .call()
  1102. .unwrap();
  1103. assert_eq!(
  1104. returns,
  1105. BorshToken::Tuple(vec![
  1106. BorshToken::Uint {
  1107. width: 64,
  1108. value: BigInt::zero(),
  1109. },
  1110. BorshToken::Bool(false),
  1111. ])
  1112. );
  1113. let returns = vm
  1114. .function("subscript")
  1115. .arguments(&[BorshToken::Uint {
  1116. width: 32,
  1117. value: BigInt::from(2u8),
  1118. }])
  1119. .accounts(vec![("dataAccount", data_account)])
  1120. .call()
  1121. .unwrap();
  1122. assert_eq!(
  1123. returns,
  1124. BorshToken::Tuple(vec![
  1125. BorshToken::Uint {
  1126. width: 64,
  1127. value: BigInt::from(12313123141123213u64),
  1128. },
  1129. BorshToken::Bool(true),
  1130. ]),
  1131. );
  1132. let returns = vm
  1133. .function("copy")
  1134. .accounts(vec![("dataAccount", data_account)])
  1135. .call()
  1136. .unwrap();
  1137. assert_eq!(
  1138. returns,
  1139. BorshToken::Array(vec![
  1140. BorshToken::Tuple(vec![
  1141. BorshToken::Uint {
  1142. width: 64,
  1143. value: BigInt::from(13819038012u64)
  1144. },
  1145. BorshToken::Bool(true),
  1146. ]),
  1147. BorshToken::Tuple(vec![
  1148. BorshToken::Uint {
  1149. width: 64,
  1150. value: BigInt::zero(),
  1151. },
  1152. BorshToken::Bool(false),
  1153. ]),
  1154. BorshToken::Tuple(vec![
  1155. BorshToken::Uint {
  1156. width: 64,
  1157. value: BigInt::from(12313123141123213u64),
  1158. },
  1159. BorshToken::Bool(true),
  1160. ]),
  1161. ])
  1162. );
  1163. let returns = vm
  1164. .function("pop")
  1165. .accounts(vec![("dataAccount", data_account)])
  1166. .call()
  1167. .unwrap();
  1168. assert_eq!(
  1169. returns,
  1170. BorshToken::Tuple(vec![
  1171. BorshToken::Uint {
  1172. width: 64,
  1173. value: BigInt::from(12313123141123213u64),
  1174. },
  1175. BorshToken::Bool(true),
  1176. ])
  1177. );
  1178. let returns = vm
  1179. .function("len")
  1180. .accounts(vec![("dataAccount", data_account)])
  1181. .call()
  1182. .unwrap();
  1183. assert_eq!(
  1184. returns,
  1185. BorshToken::Uint {
  1186. width: 256,
  1187. value: BigInt::from(2u8),
  1188. }
  1189. );
  1190. vm.function("set")
  1191. .arguments(&[BorshToken::Array(vec![
  1192. BorshToken::Tuple(vec![
  1193. BorshToken::Uint {
  1194. width: 64,
  1195. value: BigInt::one(),
  1196. },
  1197. BorshToken::Bool(false),
  1198. ]),
  1199. BorshToken::Tuple(vec![
  1200. BorshToken::Uint {
  1201. width: 64,
  1202. value: BigInt::from(2u8),
  1203. },
  1204. BorshToken::Bool(true),
  1205. ]),
  1206. BorshToken::Tuple(vec![
  1207. BorshToken::Uint {
  1208. width: 64,
  1209. value: BigInt::from(3u8),
  1210. },
  1211. BorshToken::Bool(false),
  1212. ]),
  1213. BorshToken::Tuple(vec![
  1214. BorshToken::Uint {
  1215. width: 64,
  1216. value: BigInt::from(4u8),
  1217. },
  1218. BorshToken::Bool(true),
  1219. ]),
  1220. BorshToken::Tuple(vec![
  1221. BorshToken::Uint {
  1222. width: 64,
  1223. value: BigInt::from(5u8),
  1224. },
  1225. BorshToken::Bool(false),
  1226. ]),
  1227. BorshToken::Tuple(vec![
  1228. BorshToken::Uint {
  1229. width: 64,
  1230. value: BigInt::from(6u8),
  1231. },
  1232. BorshToken::Bool(true),
  1233. ]),
  1234. ])])
  1235. .accounts(vec![("dataAccount", data_account)])
  1236. .call();
  1237. let returns = vm
  1238. .function("copy")
  1239. .accounts(vec![("dataAccount", data_account)])
  1240. .call()
  1241. .unwrap();
  1242. assert_eq!(
  1243. returns,
  1244. BorshToken::Array(vec![
  1245. BorshToken::Tuple(vec![
  1246. BorshToken::Uint {
  1247. width: 64,
  1248. value: BigInt::one(),
  1249. },
  1250. BorshToken::Bool(false)
  1251. ]),
  1252. BorshToken::Tuple(vec![
  1253. BorshToken::Uint {
  1254. width: 64,
  1255. value: BigInt::from(2u8),
  1256. },
  1257. BorshToken::Bool(true)
  1258. ]),
  1259. BorshToken::Tuple(vec![
  1260. BorshToken::Uint {
  1261. width: 64,
  1262. value: BigInt::from(3u8),
  1263. },
  1264. BorshToken::Bool(false)
  1265. ]),
  1266. BorshToken::Tuple(vec![
  1267. BorshToken::Uint {
  1268. width: 64,
  1269. value: BigInt::from(4u8),
  1270. },
  1271. BorshToken::Bool(true)
  1272. ]),
  1273. BorshToken::Tuple(vec![
  1274. BorshToken::Uint {
  1275. width: 64,
  1276. value: BigInt::from(5u8),
  1277. },
  1278. BorshToken::Bool(false)
  1279. ]),
  1280. BorshToken::Tuple(vec![
  1281. BorshToken::Uint {
  1282. width: 64,
  1283. value: BigInt::from(6u8),
  1284. },
  1285. BorshToken::Bool(true)
  1286. ]),
  1287. ]),
  1288. );
  1289. vm.function("rm")
  1290. .accounts(vec![("dataAccount", data_account)])
  1291. .call();
  1292. let returns = vm
  1293. .function("len")
  1294. .accounts(vec![("dataAccount", data_account)])
  1295. .call()
  1296. .unwrap();
  1297. assert_eq!(
  1298. returns,
  1299. BorshToken::Uint {
  1300. width: 256,
  1301. value: BigInt::zero(),
  1302. }
  1303. );
  1304. }
  1305. #[test]
  1306. fn array_literal() {
  1307. let mut vm = build_solidity(
  1308. r#"
  1309. contract foo {
  1310. int64 constant foo = 1;
  1311. int64 bar = 2;
  1312. function list() public returns (int64[3]) {
  1313. return [foo, bar, 3];
  1314. }
  1315. }"#,
  1316. );
  1317. let data_account = vm.initialize_data_account();
  1318. vm.function("new")
  1319. .accounts(vec![("dataAccount", data_account)])
  1320. .call();
  1321. let returns = vm
  1322. .function("list")
  1323. .accounts(vec![("dataAccount", data_account)])
  1324. .call()
  1325. .unwrap();
  1326. assert_eq!(
  1327. returns,
  1328. BorshToken::FixedArray(vec![
  1329. BorshToken::Int {
  1330. width: 64,
  1331. value: BigInt::one(),
  1332. },
  1333. BorshToken::Int {
  1334. width: 64,
  1335. value: BigInt::from(2u8),
  1336. },
  1337. BorshToken::Int {
  1338. width: 64,
  1339. value: BigInt::from(3u8),
  1340. },
  1341. ])
  1342. );
  1343. }
  1344. #[test]
  1345. fn storage_pop_push() {
  1346. let mut vm = build_solidity(
  1347. r#"
  1348. contract Testing {
  1349. struct NonConstantStruct {
  1350. string[] b;
  1351. }
  1352. string[] vec_2;
  1353. NonConstantStruct[] public complex_array;
  1354. function fn1() public {
  1355. vec_2.push("tea");
  1356. }
  1357. function fn2() public {
  1358. vec_2.push("coffee");
  1359. }
  1360. function fn3() public {
  1361. NonConstantStruct memory ss = NonConstantStruct(vec_2);
  1362. complex_array.push(ss);
  1363. }
  1364. function fn4() public {
  1365. vec_2.pop();
  1366. }
  1367. function fn5() public {
  1368. vec_2.pop();
  1369. }
  1370. function fn6() public {
  1371. vec_2.push("cortado");
  1372. }
  1373. function fn7() public {
  1374. vec_2.push("cappuccino");
  1375. }
  1376. function fn8() public {
  1377. NonConstantStruct memory sr = NonConstantStruct(vec_2);
  1378. complex_array.push(sr);
  1379. }
  1380. function clear() public {
  1381. vec_2 = new string[](0);
  1382. complex_array = new NonConstantStruct[](0);
  1383. }
  1384. }"#,
  1385. );
  1386. let data_account = vm.initialize_data_account();
  1387. vm.function("new")
  1388. .accounts(vec![("dataAccount", data_account)])
  1389. .call();
  1390. vm.function("fn1")
  1391. .accounts(vec![("dataAccount", data_account)])
  1392. .call();
  1393. vm.function("fn2")
  1394. .accounts(vec![("dataAccount", data_account)])
  1395. .call();
  1396. vm.function("fn3")
  1397. .accounts(vec![("dataAccount", data_account)])
  1398. .call();
  1399. vm.function("fn4")
  1400. .accounts(vec![("dataAccount", data_account)])
  1401. .call();
  1402. vm.function("fn5")
  1403. .accounts(vec![("dataAccount", data_account)])
  1404. .call();
  1405. vm.function("fn6")
  1406. .accounts(vec![("dataAccount", data_account)])
  1407. .call();
  1408. vm.function("fn7")
  1409. .accounts(vec![("dataAccount", data_account)])
  1410. .call();
  1411. vm.function("fn8")
  1412. .accounts(vec![("dataAccount", data_account)])
  1413. .call();
  1414. vm.function("clear")
  1415. .accounts(vec![("dataAccount", data_account)])
  1416. .call();
  1417. // make sure every thing has been freed
  1418. assert_eq!(vm.validate_account_data_heap(&Pubkey(data_account)), 0);
  1419. }
  1420. #[test]
  1421. fn initialization_with_literal() {
  1422. let mut vm = build_solidity(
  1423. r#"
  1424. contract Testing {
  1425. address[] splitAddresses;
  1426. function split(address addr1, address addr2) public {
  1427. splitAddresses = [addr1, addr2];
  1428. }
  1429. function getIdx(uint32 idx) public view returns (address) {
  1430. return splitAddresses[idx];
  1431. }
  1432. function getVec(uint32 a, uint32 b) public pure returns (uint32[] memory) {
  1433. uint32[] memory vec;
  1434. vec = [a, b];
  1435. return vec;
  1436. }
  1437. }
  1438. "#,
  1439. );
  1440. let data_account = vm.initialize_data_account();
  1441. vm.function("new")
  1442. .accounts(vec![("dataAccount", data_account)])
  1443. .call();
  1444. let mut addr1: Vec<u8> = vec![0; 32];
  1445. addr1[0] = 1;
  1446. let mut addr2: Vec<u8> = vec![0; 32];
  1447. addr2[0] = 2;
  1448. let _ = vm
  1449. .function("split")
  1450. .arguments(&[
  1451. BorshToken::FixedBytes(addr1[..].to_vec()),
  1452. BorshToken::FixedBytes(addr2[..].to_vec()),
  1453. ])
  1454. .accounts(vec![("dataAccount", data_account)])
  1455. .call();
  1456. let returns = vm
  1457. .function("getIdx")
  1458. .arguments(&[BorshToken::Uint {
  1459. width: 32,
  1460. value: BigInt::zero(),
  1461. }])
  1462. .accounts(vec![("dataAccount", data_account)])
  1463. .call()
  1464. .unwrap();
  1465. let returned_addr1 = returns.into_fixed_bytes().unwrap();
  1466. assert_eq!(addr1, returned_addr1);
  1467. let returns = vm
  1468. .function("getIdx")
  1469. .arguments(&[BorshToken::Uint {
  1470. width: 32,
  1471. value: BigInt::one(),
  1472. }])
  1473. .accounts(vec![("dataAccount", data_account)])
  1474. .call()
  1475. .unwrap();
  1476. let returned_addr2 = returns.into_fixed_bytes().unwrap();
  1477. assert_eq!(addr2, returned_addr2);
  1478. let returns = vm
  1479. .function("getVec")
  1480. .arguments(&[
  1481. BorshToken::Uint {
  1482. width: 32,
  1483. value: BigInt::from(563u16),
  1484. },
  1485. BorshToken::Uint {
  1486. width: 32,
  1487. value: BigInt::from(895u16),
  1488. },
  1489. ])
  1490. .call()
  1491. .unwrap();
  1492. let array = returns.into_array().unwrap();
  1493. assert_eq!(
  1494. array,
  1495. vec![
  1496. BorshToken::Uint {
  1497. width: 32,
  1498. value: BigInt::from(563u16),
  1499. },
  1500. BorshToken::Uint {
  1501. width: 32,
  1502. value: BigInt::from(895u16),
  1503. },
  1504. ]
  1505. );
  1506. }
  1507. #[test]
  1508. fn dynamic_array_push() {
  1509. let mut runtime = build_solidity(
  1510. r#"
  1511. pragma solidity 0;
  1512. contract foo {
  1513. function test() public {
  1514. int[] bar = (new int[])(1);
  1515. bar[0] = 128;
  1516. bar.push(64);
  1517. assert(bar.length == 2);
  1518. assert(bar[1] == 64);
  1519. }
  1520. }
  1521. "#,
  1522. );
  1523. let data_account = runtime.initialize_data_account();
  1524. runtime
  1525. .function("new")
  1526. .accounts(vec![("dataAccount", data_account)])
  1527. .call();
  1528. runtime.function("test").call();
  1529. let mut runtime = build_solidity(
  1530. r#"
  1531. pragma solidity 0;
  1532. contract foo {
  1533. function test() public {
  1534. bytes bar = (new bytes)(1);
  1535. bar[0] = 128;
  1536. bar.push(64);
  1537. assert(bar.length == 2);
  1538. assert(bar[1] == 64);
  1539. }
  1540. }
  1541. "#,
  1542. );
  1543. let data_account = runtime.initialize_data_account();
  1544. runtime
  1545. .function("new")
  1546. .accounts(vec![("dataAccount", data_account)])
  1547. .call();
  1548. runtime.function("test").call();
  1549. let mut runtime = build_solidity(
  1550. r#"
  1551. pragma solidity 0;
  1552. contract foo {
  1553. struct s {
  1554. int32 f1;
  1555. bool f2;
  1556. }
  1557. function test() public {
  1558. s[] bar = new s[](1);
  1559. bar[0] = s({f1: 0, f2: false});
  1560. bar.push(s({f1: 1, f2: true}));
  1561. assert(bar.length == 2);
  1562. assert(bar[1].f1 == 1);
  1563. assert(bar[1].f2 == true);
  1564. }
  1565. }
  1566. "#,
  1567. );
  1568. let data_account = runtime.initialize_data_account();
  1569. runtime
  1570. .function("new")
  1571. .accounts(vec![("dataAccount", data_account)])
  1572. .call();
  1573. runtime.function("test").call();
  1574. let mut runtime = build_solidity(
  1575. r#"
  1576. pragma solidity 0;
  1577. contract foo {
  1578. enum enum1 { val1, val2, val3 }
  1579. function test() public {
  1580. enum1[] bar = new enum1[](1);
  1581. bar[0] = enum1.val1;
  1582. bar.push(enum1.val2);
  1583. assert(bar.length == 2);
  1584. assert(bar[1] == enum1.val2);
  1585. }
  1586. }
  1587. "#,
  1588. );
  1589. let data_account = runtime.initialize_data_account();
  1590. runtime
  1591. .function("new")
  1592. .accounts(vec![("dataAccount", data_account)])
  1593. .call();
  1594. runtime.function("test").call();
  1595. // push() returns a reference to the thing
  1596. let mut runtime = build_solidity(
  1597. r#"
  1598. pragma solidity 0;
  1599. contract foo {
  1600. struct s {
  1601. int32 f1;
  1602. bool f2;
  1603. }
  1604. function test() public {
  1605. s[] bar = new s[](0);
  1606. s memory n = bar.push();
  1607. n.f1 = 102;
  1608. n.f2 = true;
  1609. assert(bar[0].f1 == 102);
  1610. assert(bar[0].f2 == true);
  1611. }
  1612. }"#,
  1613. );
  1614. let data_account = runtime.initialize_data_account();
  1615. runtime
  1616. .function("new")
  1617. .accounts(vec![("dataAccount", data_account)])
  1618. .call();
  1619. runtime.function("test").call();
  1620. }
  1621. #[test]
  1622. fn dynamic_array_pop() {
  1623. let mut runtime = build_solidity(
  1624. r#"
  1625. pragma solidity 0;
  1626. contract foo {
  1627. function test() public {
  1628. int[] bar = new int[](1);
  1629. bar[0] = 128;
  1630. assert(bar.length == 1);
  1631. assert(128 == bar.pop());
  1632. assert(bar.length == 0);
  1633. }
  1634. }
  1635. "#,
  1636. );
  1637. let data_account = runtime.initialize_data_account();
  1638. runtime
  1639. .function("new")
  1640. .accounts(vec![("dataAccount", data_account)])
  1641. .call();
  1642. runtime.function("test").call();
  1643. let mut runtime = build_solidity(
  1644. r#"
  1645. pragma solidity 0;
  1646. contract foo {
  1647. function test() public {
  1648. bytes bar = new bytes(1);
  1649. bar[0] = 128;
  1650. assert(bar.length == 1);
  1651. assert(128 == bar.pop());
  1652. assert(bar.length == 0);
  1653. }
  1654. }
  1655. "#,
  1656. );
  1657. let data_account = runtime.initialize_data_account();
  1658. runtime
  1659. .function("new")
  1660. .accounts(vec![("dataAccount", data_account)])
  1661. .call();
  1662. runtime.function("test").call();
  1663. let mut runtime = build_solidity(
  1664. r#"
  1665. pragma solidity 0;
  1666. contract foo {
  1667. struct s {
  1668. int32 f1;
  1669. bool f2;
  1670. }
  1671. function test() public {
  1672. s[] bar = new s[](1);
  1673. bar[0] = s(128, true);
  1674. assert(bar.length == 1);
  1675. s baz = bar.pop();
  1676. assert(baz.f1 == 128);
  1677. assert(baz.f2 == true);
  1678. assert(bar.length == 0);
  1679. }
  1680. }
  1681. "#,
  1682. );
  1683. let data_account = runtime.initialize_data_account();
  1684. runtime
  1685. .function("new")
  1686. .accounts(vec![("dataAccount", data_account)])
  1687. .call();
  1688. runtime.function("test").call();
  1689. let mut runtime = build_solidity(
  1690. r#"
  1691. pragma solidity 0;
  1692. contract foo {
  1693. enum enum1 { val1, val2, val3 }
  1694. function test() public {
  1695. enum1[] bar = new enum1[](1);
  1696. bar[0] = enum1.val2;
  1697. assert(bar.length == 1);
  1698. assert(enum1.val2 == bar.pop());
  1699. assert(bar.length == 0);
  1700. }
  1701. }
  1702. "#,
  1703. );
  1704. let data_account = runtime.initialize_data_account();
  1705. runtime
  1706. .function("new")
  1707. .accounts(vec![("dataAccount", data_account)])
  1708. .call();
  1709. runtime.function("test").call();
  1710. }
  1711. #[test]
  1712. #[should_panic]
  1713. fn dynamic_array_pop_empty_array() {
  1714. let mut runtime = build_solidity(
  1715. r#"
  1716. pragma solidity 0;
  1717. contract foo {
  1718. function test() public returns (int) {
  1719. int[] bar = new int[](0);
  1720. return bar.pop();
  1721. }
  1722. }"#,
  1723. );
  1724. let data_account = runtime.initialize_data_account();
  1725. runtime
  1726. .function("new")
  1727. .accounts(vec![("dataAccount", data_account)])
  1728. .call();
  1729. runtime
  1730. .function("test")
  1731. .accounts(vec![("dataAccount", data_account)])
  1732. .call();
  1733. }
  1734. #[test]
  1735. #[should_panic]
  1736. fn dynamic_array_pop_bounds() {
  1737. let mut runtime = build_solidity(
  1738. r#"
  1739. pragma solidity 0;
  1740. contract foo {
  1741. function test() public {
  1742. int[] bar = new int[](1);
  1743. bar[0] = 12;
  1744. bar.pop();
  1745. assert(bar[0] == 12);
  1746. }
  1747. }"#,
  1748. );
  1749. let data_account = runtime.initialize_data_account();
  1750. runtime
  1751. .function("new")
  1752. .accounts(vec![("dataAccount", data_account)])
  1753. .call();
  1754. runtime
  1755. .function("test")
  1756. .accounts(vec![("dataAccount", data_account)])
  1757. .call();
  1758. }
  1759. #[test]
  1760. fn dynamic_array_push_pop_loop() {
  1761. let mut runtime = build_solidity(
  1762. r#"
  1763. contract foo {
  1764. function test() public {
  1765. uint32[] bar1 = new uint32[](0);
  1766. uint32[] bar2 = new uint32[](0);
  1767. // each time we call a system call, the heap is checked
  1768. // for consistency. So do a print() after each operation
  1769. for (uint64 i = 1; i < 160; i++) {
  1770. if ((i % 10) == 0) {
  1771. bar1.pop();
  1772. print("bar1.pop");
  1773. bar2.pop();
  1774. print("bar2.pop");
  1775. } else {
  1776. uint32 v = bar1.length;
  1777. bar1.push(v);
  1778. print("bar1.push");
  1779. bar2.push(v);
  1780. print("bar2.push");
  1781. }
  1782. }
  1783. assert(bar1.length == bar2.length);
  1784. for (uint32 i = 0; i < bar1.length; i++) {
  1785. assert(bar1[i] == i);
  1786. assert(bar2[i] == i);
  1787. }
  1788. }
  1789. }"#,
  1790. );
  1791. let data_account = runtime.initialize_data_account();
  1792. runtime
  1793. .function("new")
  1794. .accounts(vec![("dataAccount", data_account)])
  1795. .call();
  1796. runtime.function("test").call();
  1797. let mut runtime = build_solidity(
  1798. r#"
  1799. contract foo {
  1800. function test() public {
  1801. bytes bar1 = new bytes(0);
  1802. bytes bar2 = new bytes(0);
  1803. // each time we call a system call, the heap is checked
  1804. // for consistency. So do a print() after each operation
  1805. for (uint64 i = 1; i < 160; i++) {
  1806. if ((i % 10) == 0) {
  1807. bar1.pop();
  1808. print("bar1.pop");
  1809. bar2.pop();
  1810. print("bar2.pop");
  1811. } else {
  1812. uint8 v = uint8(bar1.length);
  1813. bar1.push(v);
  1814. print("bar1.push");
  1815. bar2.push(v);
  1816. print("bar2.push");
  1817. }
  1818. }
  1819. assert(bar1.length == bar2.length);
  1820. for (uint32 i = 0; i < bar1.length; i++) {
  1821. uint8 v = uint8(i);
  1822. print("{}.{}.{}".format(v, bar1[i], bar2[i]));
  1823. assert(bar1[i] == v);
  1824. assert(bar2[i] == v);
  1825. }
  1826. }
  1827. }"#,
  1828. );
  1829. let data_account = runtime.initialize_data_account();
  1830. runtime
  1831. .function("new")
  1832. .accounts(vec![("dataAccount", data_account)])
  1833. .call();
  1834. runtime.function("test").call();
  1835. }
  1836. #[test]
  1837. fn double_index() {
  1838. let src = r#"
  1839. contract RH {
  1840. function calc(uint256[] memory separators, int256[] memory params) public pure returns (int256[4] memory) {
  1841. int256 stopLimit = params[separators[4]];
  1842. int256 contractedValueRatio = params[separators[6]];
  1843. return [stopLimit, contractedValueRatio, 3, 4];
  1844. }
  1845. }
  1846. "#;
  1847. let mut vm = build_solidity(src);
  1848. let data_account = vm.initialize_data_account();
  1849. vm.function("new")
  1850. .accounts(vec![("dataAccount", data_account)])
  1851. .call();
  1852. let separators = BorshToken::Array(vec![
  1853. BorshToken::Int {
  1854. width: 256,
  1855. value: BigInt::from(25u8),
  1856. },
  1857. BorshToken::Int {
  1858. width: 256,
  1859. value: BigInt::from(25u8),
  1860. },
  1861. BorshToken::Int {
  1862. width: 256,
  1863. value: BigInt::from(25u8),
  1864. },
  1865. BorshToken::Int {
  1866. width: 256,
  1867. value: BigInt::from(25u8),
  1868. },
  1869. BorshToken::Int {
  1870. width: 256,
  1871. value: BigInt::from(1u8),
  1872. },
  1873. BorshToken::Int {
  1874. width: 256,
  1875. value: BigInt::from(25u8),
  1876. },
  1877. BorshToken::Int {
  1878. width: 256,
  1879. value: BigInt::from(0u8),
  1880. },
  1881. ]);
  1882. let params = BorshToken::Array(vec![
  1883. BorshToken::Int {
  1884. width: 256,
  1885. value: BigInt::from(80u8),
  1886. },
  1887. BorshToken::Int {
  1888. width: 256,
  1889. value: BigInt::from(98u8),
  1890. },
  1891. ]);
  1892. let returns = vm
  1893. .function("calc")
  1894. .arguments(&[separators, params])
  1895. .call()
  1896. .unwrap();
  1897. assert_eq!(
  1898. returns,
  1899. BorshToken::FixedArray(vec![
  1900. BorshToken::Int {
  1901. width: 256,
  1902. value: BigInt::from(98u8),
  1903. },
  1904. BorshToken::Int {
  1905. width: 256,
  1906. value: BigInt::from(80u8),
  1907. },
  1908. BorshToken::Int {
  1909. width: 256,
  1910. value: BigInt::from(3u8),
  1911. },
  1912. BorshToken::Int {
  1913. width: 256,
  1914. value: BigInt::from(4u8),
  1915. },
  1916. ])
  1917. );
  1918. }
  1919. #[test]
  1920. fn push_empty_array() {
  1921. let src = r#"
  1922. contract MyTest {
  1923. function foo() public pure returns (bytes memory) {
  1924. bytes b1 = hex"41";
  1925. bytes b2 = hex"41";
  1926. b2.push(0x41);
  1927. return (b1);
  1928. }
  1929. function foo2() public pure returns (uint64) {
  1930. uint64[] a;
  1931. a.push(20);
  1932. return a[0];
  1933. }
  1934. }
  1935. "#;
  1936. let mut vm = build_solidity(src);
  1937. let data_account = vm.initialize_data_account();
  1938. vm.function("new")
  1939. .accounts(vec![("dataAccount", data_account)])
  1940. .call();
  1941. let ret = vm.function("foo").call().unwrap();
  1942. assert_eq!(ret, BorshToken::Bytes(vec![65]));
  1943. let ret = vm.function("foo2").call().unwrap();
  1944. assert_eq!(
  1945. ret,
  1946. BorshToken::Uint {
  1947. width: 64,
  1948. value: BigInt::from(20),
  1949. }
  1950. );
  1951. }