arrays.rs 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234
  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::new();
  1445. addr1.resize(32, 0);
  1446. addr1[0] = 1;
  1447. let mut addr2: Vec<u8> = Vec::new();
  1448. addr2.resize(32, 0);
  1449. addr2[0] = 2;
  1450. let _ = vm
  1451. .function("split")
  1452. .arguments(&[
  1453. BorshToken::FixedBytes(addr1[..].to_vec()),
  1454. BorshToken::FixedBytes(addr2[..].to_vec()),
  1455. ])
  1456. .accounts(vec![("dataAccount", data_account)])
  1457. .call();
  1458. let returns = vm
  1459. .function("getIdx")
  1460. .arguments(&[BorshToken::Uint {
  1461. width: 32,
  1462. value: BigInt::zero(),
  1463. }])
  1464. .accounts(vec![("dataAccount", data_account)])
  1465. .call()
  1466. .unwrap();
  1467. let returned_addr1 = returns.into_fixed_bytes().unwrap();
  1468. assert_eq!(addr1, returned_addr1);
  1469. let returns = vm
  1470. .function("getIdx")
  1471. .arguments(&[BorshToken::Uint {
  1472. width: 32,
  1473. value: BigInt::one(),
  1474. }])
  1475. .accounts(vec![("dataAccount", data_account)])
  1476. .call()
  1477. .unwrap();
  1478. let returned_addr2 = returns.into_fixed_bytes().unwrap();
  1479. assert_eq!(addr2, returned_addr2);
  1480. let returns = vm
  1481. .function("getVec")
  1482. .arguments(&[
  1483. BorshToken::Uint {
  1484. width: 32,
  1485. value: BigInt::from(563u16),
  1486. },
  1487. BorshToken::Uint {
  1488. width: 32,
  1489. value: BigInt::from(895u16),
  1490. },
  1491. ])
  1492. .call()
  1493. .unwrap();
  1494. let array = returns.into_array().unwrap();
  1495. assert_eq!(
  1496. array,
  1497. vec![
  1498. BorshToken::Uint {
  1499. width: 32,
  1500. value: BigInt::from(563u16),
  1501. },
  1502. BorshToken::Uint {
  1503. width: 32,
  1504. value: BigInt::from(895u16),
  1505. },
  1506. ]
  1507. );
  1508. }
  1509. #[test]
  1510. fn dynamic_array_push() {
  1511. let mut runtime = build_solidity(
  1512. r#"
  1513. pragma solidity 0;
  1514. contract foo {
  1515. function test() public {
  1516. int[] bar = (new int[])(1);
  1517. bar[0] = 128;
  1518. bar.push(64);
  1519. assert(bar.length == 2);
  1520. assert(bar[1] == 64);
  1521. }
  1522. }
  1523. "#,
  1524. );
  1525. let data_account = runtime.initialize_data_account();
  1526. runtime
  1527. .function("new")
  1528. .accounts(vec![("dataAccount", data_account)])
  1529. .call();
  1530. runtime.function("test").call();
  1531. let mut runtime = build_solidity(
  1532. r#"
  1533. pragma solidity 0;
  1534. contract foo {
  1535. function test() public {
  1536. bytes bar = (new bytes)(1);
  1537. bar[0] = 128;
  1538. bar.push(64);
  1539. assert(bar.length == 2);
  1540. assert(bar[1] == 64);
  1541. }
  1542. }
  1543. "#,
  1544. );
  1545. let data_account = runtime.initialize_data_account();
  1546. runtime
  1547. .function("new")
  1548. .accounts(vec![("dataAccount", data_account)])
  1549. .call();
  1550. runtime.function("test").call();
  1551. let mut runtime = build_solidity(
  1552. r#"
  1553. pragma solidity 0;
  1554. contract foo {
  1555. struct s {
  1556. int32 f1;
  1557. bool f2;
  1558. }
  1559. function test() public {
  1560. s[] bar = new s[](1);
  1561. bar[0] = s({f1: 0, f2: false});
  1562. bar.push(s({f1: 1, f2: true}));
  1563. assert(bar.length == 2);
  1564. assert(bar[1].f1 == 1);
  1565. assert(bar[1].f2 == true);
  1566. }
  1567. }
  1568. "#,
  1569. );
  1570. let data_account = runtime.initialize_data_account();
  1571. runtime
  1572. .function("new")
  1573. .accounts(vec![("dataAccount", data_account)])
  1574. .call();
  1575. runtime.function("test").call();
  1576. let mut runtime = build_solidity(
  1577. r#"
  1578. pragma solidity 0;
  1579. contract foo {
  1580. enum enum1 { val1, val2, val3 }
  1581. function test() public {
  1582. enum1[] bar = new enum1[](1);
  1583. bar[0] = enum1.val1;
  1584. bar.push(enum1.val2);
  1585. assert(bar.length == 2);
  1586. assert(bar[1] == enum1.val2);
  1587. }
  1588. }
  1589. "#,
  1590. );
  1591. let data_account = runtime.initialize_data_account();
  1592. runtime
  1593. .function("new")
  1594. .accounts(vec![("dataAccount", data_account)])
  1595. .call();
  1596. runtime.function("test").call();
  1597. // push() returns a reference to the thing
  1598. let mut runtime = build_solidity(
  1599. r#"
  1600. pragma solidity 0;
  1601. contract foo {
  1602. struct s {
  1603. int32 f1;
  1604. bool f2;
  1605. }
  1606. function test() public {
  1607. s[] bar = new s[](0);
  1608. s memory n = bar.push();
  1609. n.f1 = 102;
  1610. n.f2 = true;
  1611. assert(bar[0].f1 == 102);
  1612. assert(bar[0].f2 == true);
  1613. }
  1614. }"#,
  1615. );
  1616. let data_account = runtime.initialize_data_account();
  1617. runtime
  1618. .function("new")
  1619. .accounts(vec![("dataAccount", data_account)])
  1620. .call();
  1621. runtime.function("test").call();
  1622. }
  1623. #[test]
  1624. fn dynamic_array_pop() {
  1625. let mut runtime = build_solidity(
  1626. r#"
  1627. pragma solidity 0;
  1628. contract foo {
  1629. function test() public {
  1630. int[] bar = new int[](1);
  1631. bar[0] = 128;
  1632. assert(bar.length == 1);
  1633. assert(128 == bar.pop());
  1634. assert(bar.length == 0);
  1635. }
  1636. }
  1637. "#,
  1638. );
  1639. let data_account = runtime.initialize_data_account();
  1640. runtime
  1641. .function("new")
  1642. .accounts(vec![("dataAccount", data_account)])
  1643. .call();
  1644. runtime.function("test").call();
  1645. let mut runtime = build_solidity(
  1646. r#"
  1647. pragma solidity 0;
  1648. contract foo {
  1649. function test() public {
  1650. bytes bar = new bytes(1);
  1651. bar[0] = 128;
  1652. assert(bar.length == 1);
  1653. assert(128 == bar.pop());
  1654. assert(bar.length == 0);
  1655. }
  1656. }
  1657. "#,
  1658. );
  1659. let data_account = runtime.initialize_data_account();
  1660. runtime
  1661. .function("new")
  1662. .accounts(vec![("dataAccount", data_account)])
  1663. .call();
  1664. runtime.function("test").call();
  1665. let mut runtime = build_solidity(
  1666. r#"
  1667. pragma solidity 0;
  1668. contract foo {
  1669. struct s {
  1670. int32 f1;
  1671. bool f2;
  1672. }
  1673. function test() public {
  1674. s[] bar = new s[](1);
  1675. bar[0] = s(128, true);
  1676. assert(bar.length == 1);
  1677. s baz = bar.pop();
  1678. assert(baz.f1 == 128);
  1679. assert(baz.f2 == true);
  1680. assert(bar.length == 0);
  1681. }
  1682. }
  1683. "#,
  1684. );
  1685. let data_account = runtime.initialize_data_account();
  1686. runtime
  1687. .function("new")
  1688. .accounts(vec![("dataAccount", data_account)])
  1689. .call();
  1690. runtime.function("test").call();
  1691. let mut runtime = build_solidity(
  1692. r#"
  1693. pragma solidity 0;
  1694. contract foo {
  1695. enum enum1 { val1, val2, val3 }
  1696. function test() public {
  1697. enum1[] bar = new enum1[](1);
  1698. bar[0] = enum1.val2;
  1699. assert(bar.length == 1);
  1700. assert(enum1.val2 == bar.pop());
  1701. assert(bar.length == 0);
  1702. }
  1703. }
  1704. "#,
  1705. );
  1706. let data_account = runtime.initialize_data_account();
  1707. runtime
  1708. .function("new")
  1709. .accounts(vec![("dataAccount", data_account)])
  1710. .call();
  1711. runtime.function("test").call();
  1712. }
  1713. #[test]
  1714. #[should_panic]
  1715. fn dynamic_array_pop_empty_array() {
  1716. let mut runtime = build_solidity(
  1717. r#"
  1718. pragma solidity 0;
  1719. contract foo {
  1720. function test() public returns (int) {
  1721. int[] bar = new int[](0);
  1722. return bar.pop();
  1723. }
  1724. }"#,
  1725. );
  1726. let data_account = runtime.initialize_data_account();
  1727. runtime
  1728. .function("new")
  1729. .accounts(vec![("dataAccount", data_account)])
  1730. .call();
  1731. runtime
  1732. .function("test")
  1733. .accounts(vec![("dataAccount", data_account)])
  1734. .call();
  1735. }
  1736. #[test]
  1737. #[should_panic]
  1738. fn dynamic_array_pop_bounds() {
  1739. let mut runtime = build_solidity(
  1740. r#"
  1741. pragma solidity 0;
  1742. contract foo {
  1743. function test() public {
  1744. int[] bar = new int[](1);
  1745. bar[0] = 12;
  1746. bar.pop();
  1747. assert(bar[0] == 12);
  1748. }
  1749. }"#,
  1750. );
  1751. let data_account = runtime.initialize_data_account();
  1752. runtime
  1753. .function("new")
  1754. .accounts(vec![("dataAccount", data_account)])
  1755. .call();
  1756. runtime
  1757. .function("test")
  1758. .accounts(vec![("dataAccount", data_account)])
  1759. .call();
  1760. }
  1761. #[test]
  1762. fn dynamic_array_push_pop_loop() {
  1763. let mut runtime = build_solidity(
  1764. r#"
  1765. contract foo {
  1766. function test() public {
  1767. uint32[] bar1 = new uint32[](0);
  1768. uint32[] bar2 = new uint32[](0);
  1769. // each time we call a system call, the heap is checked
  1770. // for consistency. So do a print() after each operation
  1771. for (uint64 i = 1; i < 160; i++) {
  1772. if ((i % 10) == 0) {
  1773. bar1.pop();
  1774. print("bar1.pop");
  1775. bar2.pop();
  1776. print("bar2.pop");
  1777. } else {
  1778. uint32 v = bar1.length;
  1779. bar1.push(v);
  1780. print("bar1.push");
  1781. bar2.push(v);
  1782. print("bar2.push");
  1783. }
  1784. }
  1785. assert(bar1.length == bar2.length);
  1786. for (uint32 i = 0; i < bar1.length; i++) {
  1787. assert(bar1[i] == i);
  1788. assert(bar2[i] == i);
  1789. }
  1790. }
  1791. }"#,
  1792. );
  1793. let data_account = runtime.initialize_data_account();
  1794. runtime
  1795. .function("new")
  1796. .accounts(vec![("dataAccount", data_account)])
  1797. .call();
  1798. runtime.function("test").call();
  1799. let mut runtime = build_solidity(
  1800. r#"
  1801. contract foo {
  1802. function test() public {
  1803. bytes bar1 = new bytes(0);
  1804. bytes bar2 = new bytes(0);
  1805. // each time we call a system call, the heap is checked
  1806. // for consistency. So do a print() after each operation
  1807. for (uint64 i = 1; i < 160; i++) {
  1808. if ((i % 10) == 0) {
  1809. bar1.pop();
  1810. print("bar1.pop");
  1811. bar2.pop();
  1812. print("bar2.pop");
  1813. } else {
  1814. uint8 v = uint8(bar1.length);
  1815. bar1.push(v);
  1816. print("bar1.push");
  1817. bar2.push(v);
  1818. print("bar2.push");
  1819. }
  1820. }
  1821. assert(bar1.length == bar2.length);
  1822. for (uint32 i = 0; i < bar1.length; i++) {
  1823. uint8 v = uint8(i);
  1824. print("{}.{}.{}".format(v, bar1[i], bar2[i]));
  1825. assert(bar1[i] == v);
  1826. assert(bar2[i] == v);
  1827. }
  1828. }
  1829. }"#,
  1830. );
  1831. let data_account = runtime.initialize_data_account();
  1832. runtime
  1833. .function("new")
  1834. .accounts(vec![("dataAccount", data_account)])
  1835. .call();
  1836. runtime.function("test").call();
  1837. }
  1838. #[test]
  1839. fn double_index() {
  1840. let src = r#"
  1841. contract RH {
  1842. function calc(uint256[] memory separators, int256[] memory params) public pure returns (int256[4] memory) {
  1843. int256 stopLimit = params[separators[4]];
  1844. int256 contractedValueRatio = params[separators[6]];
  1845. return [stopLimit, contractedValueRatio, 3, 4];
  1846. }
  1847. }
  1848. "#;
  1849. let mut vm = build_solidity(src);
  1850. let data_account = vm.initialize_data_account();
  1851. vm.function("new")
  1852. .accounts(vec![("dataAccount", data_account)])
  1853. .call();
  1854. let separators = BorshToken::Array(vec![
  1855. BorshToken::Int {
  1856. width: 256,
  1857. value: BigInt::from(25u8),
  1858. },
  1859. BorshToken::Int {
  1860. width: 256,
  1861. value: BigInt::from(25u8),
  1862. },
  1863. BorshToken::Int {
  1864. width: 256,
  1865. value: BigInt::from(25u8),
  1866. },
  1867. BorshToken::Int {
  1868. width: 256,
  1869. value: BigInt::from(25u8),
  1870. },
  1871. BorshToken::Int {
  1872. width: 256,
  1873. value: BigInt::from(1u8),
  1874. },
  1875. BorshToken::Int {
  1876. width: 256,
  1877. value: BigInt::from(25u8),
  1878. },
  1879. BorshToken::Int {
  1880. width: 256,
  1881. value: BigInt::from(0u8),
  1882. },
  1883. ]);
  1884. let params = BorshToken::Array(vec![
  1885. BorshToken::Int {
  1886. width: 256,
  1887. value: BigInt::from(80u8),
  1888. },
  1889. BorshToken::Int {
  1890. width: 256,
  1891. value: BigInt::from(98u8),
  1892. },
  1893. ]);
  1894. let returns = vm
  1895. .function("calc")
  1896. .arguments(&[separators, params])
  1897. .call()
  1898. .unwrap();
  1899. assert_eq!(
  1900. returns,
  1901. BorshToken::FixedArray(vec![
  1902. BorshToken::Int {
  1903. width: 256,
  1904. value: BigInt::from(98u8),
  1905. },
  1906. BorshToken::Int {
  1907. width: 256,
  1908. value: BigInt::from(80u8),
  1909. },
  1910. BorshToken::Int {
  1911. width: 256,
  1912. value: BigInt::from(3u8),
  1913. },
  1914. BorshToken::Int {
  1915. width: 256,
  1916. value: BigInt::from(4u8),
  1917. },
  1918. ])
  1919. );
  1920. }
  1921. #[test]
  1922. fn push_empty_array() {
  1923. let src = r#"
  1924. contract MyTest {
  1925. function foo() public pure returns (bytes memory) {
  1926. bytes b1 = hex"41";
  1927. bytes b2 = hex"41";
  1928. b2.push(0x41);
  1929. return (b1);
  1930. }
  1931. function foo2() public pure returns (uint64) {
  1932. uint64[] a;
  1933. a.push(20);
  1934. return a[0];
  1935. }
  1936. }
  1937. "#;
  1938. let mut vm = build_solidity(src);
  1939. let data_account = vm.initialize_data_account();
  1940. vm.function("new")
  1941. .accounts(vec![("dataAccount", data_account)])
  1942. .call();
  1943. let ret = vm.function("foo").call().unwrap();
  1944. assert_eq!(ret, BorshToken::Bytes(vec![65]));
  1945. let ret = vm.function("foo2").call().unwrap();
  1946. assert_eq!(
  1947. ret,
  1948. BorshToken::Uint {
  1949. width: 64,
  1950. value: BigInt::from(20),
  1951. }
  1952. );
  1953. }