mappings.rs 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202
  1. // SPDX-License-Identifier: Apache-2.0
  2. use crate::{account_new, build_solidity, BorshToken};
  3. use num_bigint::BigInt;
  4. use num_traits::{One, Zero};
  5. #[test]
  6. fn simple_mapping() {
  7. let mut vm = build_solidity(
  8. r#"
  9. contract foo {
  10. mapping (uint64 => uint64) map;
  11. function set(uint64 index, uint64 val) public {
  12. map[index] = val;
  13. }
  14. function get(uint64 index) public returns (uint64) {
  15. return map[index];
  16. }
  17. function rm(uint64 index) public {
  18. delete map[index];
  19. }
  20. }"#,
  21. );
  22. let data_account = vm.initialize_data_account();
  23. vm.function("new")
  24. .accounts(vec![("dataAccount", data_account)])
  25. .call();
  26. for i in 0..10 {
  27. vm.function("set")
  28. .arguments(&[
  29. BorshToken::Uint {
  30. width: 64,
  31. value: BigInt::from(102 + i),
  32. },
  33. BorshToken::Uint {
  34. width: 64,
  35. value: BigInt::from(300331 + i),
  36. },
  37. ])
  38. .accounts(vec![("dataAccount", data_account)])
  39. .call();
  40. }
  41. for i in 0..10 {
  42. let returns = vm
  43. .function("get")
  44. .arguments(&[BorshToken::Uint {
  45. width: 64,
  46. value: BigInt::from(102 + i),
  47. }])
  48. .accounts(vec![("dataAccount", data_account)])
  49. .call()
  50. .unwrap();
  51. assert_eq!(
  52. returns,
  53. BorshToken::Uint {
  54. width: 64,
  55. value: BigInt::from(300331 + i)
  56. }
  57. );
  58. }
  59. let returns = vm
  60. .function("get")
  61. .arguments(&[BorshToken::Uint {
  62. width: 64,
  63. value: BigInt::from(101u8),
  64. }])
  65. .accounts(vec![("dataAccount", data_account)])
  66. .call()
  67. .unwrap();
  68. assert_eq!(
  69. returns,
  70. BorshToken::Uint {
  71. width: 64,
  72. value: BigInt::zero()
  73. }
  74. );
  75. vm.function("rm")
  76. .arguments(&[BorshToken::Uint {
  77. width: 64,
  78. value: BigInt::from(104u8),
  79. }])
  80. .accounts(vec![("dataAccount", data_account)])
  81. .call();
  82. for i in 0..10 {
  83. let returns = vm
  84. .function("get")
  85. .arguments(&[BorshToken::Uint {
  86. width: 64,
  87. value: BigInt::from(102 + i),
  88. }])
  89. .accounts(vec![("dataAccount", data_account)])
  90. .call()
  91. .unwrap();
  92. if 102 + i != 104 {
  93. assert_eq!(
  94. returns,
  95. BorshToken::Uint {
  96. width: 64,
  97. value: BigInt::from(300331 + i)
  98. }
  99. );
  100. } else {
  101. assert_eq!(
  102. returns,
  103. BorshToken::Uint {
  104. width: 64,
  105. value: BigInt::zero(),
  106. }
  107. );
  108. }
  109. }
  110. }
  111. #[test]
  112. fn less_simple_mapping() {
  113. let mut vm = build_solidity(
  114. r#"
  115. struct S {
  116. string f1;
  117. int64[] f2;
  118. }
  119. contract foo {
  120. mapping (uint => S) map;
  121. function set_string(uint index, string s) public {
  122. map[index].f1 = s;
  123. }
  124. function add_int(uint index, int64 n) public {
  125. map[index].f2.push(n);
  126. }
  127. function get(uint index) public returns (S) {
  128. return map[index];
  129. }
  130. function rm(uint index) public {
  131. delete map[index];
  132. }
  133. }"#,
  134. );
  135. let data_account = vm.initialize_data_account();
  136. vm.function("new")
  137. .accounts(vec![("dataAccount", data_account)])
  138. .call();
  139. vm.function(
  140. "set_string")
  141. .arguments(
  142. &[
  143. BorshToken::Uint {
  144. width: 256,
  145. value: BigInt::from(12313132131321312311213131u128)
  146. },
  147. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  148. ],
  149. )
  150. .accounts(vec![("dataAccount", data_account)])
  151. .call();
  152. vm.function("add_int")
  153. .arguments(&[
  154. BorshToken::Uint {
  155. width: 256,
  156. value: BigInt::from(12313132131321312311213131u128),
  157. },
  158. BorshToken::Int {
  159. width: 64,
  160. value: BigInt::from(102u8),
  161. },
  162. ])
  163. .accounts(vec![("dataAccount", data_account)])
  164. .call();
  165. let returns = vm
  166. .function("get")
  167. .arguments(&[BorshToken::Uint {
  168. width: 256,
  169. value: BigInt::from(12313132131321312311213131u128),
  170. }])
  171. .accounts(vec![("dataAccount", data_account)])
  172. .call()
  173. .unwrap();
  174. assert_eq!(
  175. returns,
  176. BorshToken::Tuple(vec![
  177. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  178. BorshToken::Array(vec![
  179. BorshToken::Int{
  180. width: 64,
  181. value: BigInt::from(102u8)
  182. },
  183. ]),
  184. ])
  185. );
  186. }
  187. #[test]
  188. fn string_mapping() {
  189. let mut vm = build_solidity(
  190. r#"
  191. struct S {
  192. string f1;
  193. int64[] f2;
  194. }
  195. contract foo {
  196. mapping (string => S) map;
  197. function set_string(string index, string s) public {
  198. map[index].f1 = s;
  199. }
  200. function add_int(string index, int64 n) public {
  201. map[index].f2.push(n);
  202. }
  203. function get(string index) public returns (S) {
  204. return map[index];
  205. }
  206. function rm(string index) public {
  207. delete map[index];
  208. }
  209. }"#,
  210. );
  211. let data_account = vm.initialize_data_account();
  212. vm.function("new")
  213. .accounts(vec![("dataAccount", data_account)])
  214. .call();
  215. vm.function(
  216. "set_string")
  217. .arguments(
  218. &[
  219. BorshToken::String(String::from("a")),
  220. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  221. ],
  222. )
  223. .accounts(vec![("dataAccount", data_account)])
  224. .call();
  225. vm.function("add_int")
  226. .arguments(&[
  227. BorshToken::String(String::from("a")),
  228. BorshToken::Int {
  229. width: 64,
  230. value: BigInt::from(102u8),
  231. },
  232. ])
  233. .accounts(vec![("dataAccount", data_account)])
  234. .call();
  235. let returns = vm
  236. .function("get")
  237. .arguments(&[BorshToken::String(String::from("a"))])
  238. .accounts(vec![("dataAccount", data_account)])
  239. .call()
  240. .unwrap();
  241. assert_eq!(
  242. returns,
  243. BorshToken::Tuple(vec![
  244. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  245. BorshToken::Array(vec![
  246. BorshToken::Int{
  247. width: 64,
  248. value: BigInt::from(102u8)
  249. },
  250. ]),
  251. ])
  252. );
  253. }
  254. #[test]
  255. fn contract_mapping() {
  256. let mut vm = build_solidity(
  257. r#"
  258. contract foo {
  259. mapping (address => string) public map;
  260. function set(address index, string s) public {
  261. map[index] = s;
  262. }
  263. function get(address index) public returns (string) {
  264. return map[index];
  265. }
  266. function rm(address index) public {
  267. delete map[index];
  268. }
  269. }"#,
  270. );
  271. let data_account = vm.initialize_data_account();
  272. vm.function("new")
  273. .accounts(vec![("dataAccount", data_account)])
  274. .call();
  275. let index = BorshToken::Address(account_new());
  276. vm.function(
  277. "set")
  278. .arguments(
  279. &[
  280. index.clone(),
  281. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  282. ], )
  283. .accounts(vec![("dataAccount", data_account)])
  284. .call();
  285. let returns = vm
  286. .function("get")
  287. .arguments(&[index.clone()])
  288. .accounts(vec![("dataAccount", data_account)])
  289. .call()
  290. .unwrap();
  291. assert_eq!(
  292. returns,
  293. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder"))
  294. );
  295. vm.function("rm")
  296. .arguments(&[index.clone()])
  297. .accounts(vec![("dataAccount", data_account)])
  298. .call();
  299. let returns = vm
  300. .function("get")
  301. .arguments(&[index])
  302. .accounts(vec![("dataAccount", data_account)])
  303. .call()
  304. .unwrap();
  305. assert_eq!(returns, BorshToken::String(String::from("")));
  306. }
  307. #[test]
  308. fn mapping_in_mapping() {
  309. let mut vm = build_solidity(
  310. r#"
  311. contract foo {
  312. mapping (string => mapping(int64 => byte)) public map;
  313. function set(string s, int64 n, bytes1 v) public {
  314. map[s][n] = v;
  315. }
  316. }"#,
  317. );
  318. let data_account = vm.initialize_data_account();
  319. vm.function("new")
  320. .accounts(vec![("dataAccount", data_account)])
  321. .call();
  322. vm.function("set")
  323. .arguments(&[
  324. BorshToken::String(String::from("a")),
  325. BorshToken::Int {
  326. width: 64,
  327. value: BigInt::from(102u8),
  328. },
  329. BorshToken::FixedBytes(vec![0x98]),
  330. ])
  331. .accounts(vec![("dataAccount", data_account)])
  332. .call();
  333. let returns = vm
  334. .function("map")
  335. .arguments(&[
  336. BorshToken::String(String::from("a")),
  337. BorshToken::Int {
  338. width: 64,
  339. value: BigInt::from(102u8),
  340. },
  341. ])
  342. .accounts(vec![("dataAccount", data_account)])
  343. .call()
  344. .unwrap();
  345. assert_eq!(returns, BorshToken::uint8_fixed_array(vec![0x98]));
  346. let returns = vm
  347. .function("map")
  348. .arguments(&[
  349. BorshToken::String(String::from("a")),
  350. BorshToken::Int {
  351. width: 64,
  352. value: BigInt::from(103u8),
  353. },
  354. ])
  355. .accounts(vec![("dataAccount", data_account)])
  356. .call()
  357. .unwrap();
  358. assert_eq!(returns, BorshToken::uint8_fixed_array(vec![0]));
  359. let returns = vm
  360. .function("map")
  361. .arguments(&[
  362. BorshToken::String(String::from("b")),
  363. BorshToken::Int {
  364. width: 64,
  365. value: BigInt::from(102u8),
  366. },
  367. ])
  368. .accounts(vec![("dataAccount", data_account)])
  369. .call()
  370. .unwrap();
  371. assert_eq!(returns, BorshToken::uint8_fixed_array(vec![0]));
  372. }
  373. #[test]
  374. fn sparse_array() {
  375. let mut vm = build_solidity(
  376. r#"
  377. struct S {
  378. string f1;
  379. int64[] f2;
  380. }
  381. contract foo {
  382. S[1e9] map;
  383. function set_string(uint index, string s) public {
  384. map[index].f1 = s;
  385. }
  386. function add_int(uint index, int64 n) public {
  387. map[index].f2.push(n);
  388. }
  389. function get(uint index) public returns (S) {
  390. return map[index];
  391. }
  392. function rm(uint index) public {
  393. delete map[index];
  394. }
  395. }"#,
  396. );
  397. let data_account = vm.initialize_data_account();
  398. vm.function("new")
  399. .accounts(vec![("dataAccount", data_account)])
  400. .call();
  401. vm.function(
  402. "set_string")
  403. .arguments(
  404. &[
  405. BorshToken::Uint{
  406. width: 256,
  407. value: BigInt::from(909090909u64)
  408. },
  409. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  410. ], )
  411. .accounts(vec![("dataAccount", data_account)])
  412. .call();
  413. vm.function("add_int")
  414. .arguments(&[
  415. BorshToken::Uint {
  416. width: 256,
  417. value: BigInt::from(909090909u64),
  418. },
  419. BorshToken::Int {
  420. width: 64,
  421. value: BigInt::from(102u8),
  422. },
  423. ])
  424. .accounts(vec![("dataAccount", data_account)])
  425. .call();
  426. let returns = vm
  427. .function("get")
  428. .arguments(&[BorshToken::Uint {
  429. width: 256,
  430. value: BigInt::from(909090909u64),
  431. }])
  432. .accounts(vec![("dataAccount", data_account)])
  433. .call()
  434. .unwrap();
  435. assert_eq!(
  436. returns,
  437. BorshToken::Tuple(vec![
  438. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  439. BorshToken::Array(vec![
  440. BorshToken::Int{
  441. width: 64,
  442. value: BigInt::from(102u8)
  443. },
  444. ]),
  445. ])
  446. );
  447. }
  448. #[test]
  449. fn massive_sparse_array() {
  450. let mut vm = build_solidity(
  451. r#"
  452. struct S {
  453. string f1;
  454. int64[] f2;
  455. }
  456. contract foo {
  457. S[1e24] map;
  458. function set_string(uint index, string s) public {
  459. map[index].f1 = s;
  460. }
  461. function add_int(uint index, int64 n) public {
  462. map[index].f2.push(n);
  463. }
  464. function get(uint index) public returns (S) {
  465. return map[index];
  466. }
  467. function rm(uint index) public {
  468. delete map[index];
  469. }
  470. }"#,
  471. );
  472. let data_account = vm.initialize_data_account();
  473. vm.function("new")
  474. .accounts(vec![("dataAccount", data_account)])
  475. .call();
  476. vm.function(
  477. "set_string")
  478. .arguments(
  479. &[
  480. BorshToken::Uint {
  481. width: 256,
  482. value: BigInt::from(786868768768678687686877u128)
  483. },
  484. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  485. ], )
  486. .accounts(vec![("dataAccount", data_account)])
  487. .call();
  488. vm.function("add_int")
  489. .arguments(&[
  490. BorshToken::Uint {
  491. width: 256,
  492. value: BigInt::from(786868768768678687686877u128),
  493. },
  494. BorshToken::Int {
  495. width: 64,
  496. value: BigInt::from(102u8),
  497. },
  498. ])
  499. .accounts(vec![("dataAccount", data_account)])
  500. .call();
  501. let returns = vm
  502. .function("get")
  503. .arguments(&[BorshToken::Uint {
  504. width: 256,
  505. value: BigInt::from(786868768768678687686877u128),
  506. }])
  507. .accounts(vec![("dataAccount", data_account)])
  508. .call()
  509. .unwrap();
  510. assert_eq!(
  511. returns,
  512. BorshToken::Tuple(vec![
  513. BorshToken::String(String::from("This is a string which should be a little longer than 32 bytes so we the the abi encoder")),
  514. BorshToken::Array(vec![
  515. BorshToken::Int {
  516. width: 64,
  517. value: BigInt::from(102u8)
  518. },
  519. ]),
  520. ])
  521. );
  522. }
  523. #[test]
  524. fn mapping_in_dynamic_array() {
  525. let mut vm = build_solidity(
  526. r#"
  527. contract foo {
  528. mapping (uint64 => uint64)[] public map;
  529. int64 public number;
  530. function set(uint64 array_no, uint64 index, uint64 val) public {
  531. map[array_no][index] = val;
  532. }
  533. function rm(uint64 array_no, uint64 index) public {
  534. delete map[array_no][index];
  535. }
  536. function push() public {
  537. map.push();
  538. }
  539. function pop() public {
  540. map.pop();
  541. }
  542. function setNumber(int64 x) public {
  543. number = x;
  544. }
  545. function length() public returns (uint64) {
  546. return map.length;
  547. }
  548. }"#,
  549. );
  550. let data_account = vm.initialize_data_account();
  551. vm.function("new")
  552. .accounts(vec![("dataAccount", data_account)])
  553. .call();
  554. vm.function("setNumber")
  555. .arguments(&[BorshToken::Int {
  556. width: 64,
  557. value: BigInt::from(2147483647),
  558. }])
  559. .accounts(vec![("dataAccount", data_account)])
  560. .call();
  561. vm.function("push")
  562. .accounts(vec![("dataAccount", data_account)])
  563. .call();
  564. vm.function("push")
  565. .accounts(vec![("dataAccount", data_account)])
  566. .call();
  567. for array_no in 0..2 {
  568. for i in 0..10 {
  569. vm.function("set")
  570. .arguments(&[
  571. BorshToken::Uint {
  572. width: 64,
  573. value: BigInt::from(array_no),
  574. },
  575. BorshToken::Uint {
  576. width: 64,
  577. value: BigInt::from(102 + i + array_no * 500),
  578. },
  579. BorshToken::Uint {
  580. width: 64,
  581. value: BigInt::from(300331 + i),
  582. },
  583. ])
  584. .accounts(vec![("dataAccount", data_account)])
  585. .call();
  586. }
  587. }
  588. for array_no in 0..2 {
  589. for i in 0..10 {
  590. let returns = vm
  591. .function("map")
  592. .arguments(&[
  593. BorshToken::Uint {
  594. width: 256,
  595. value: BigInt::from(array_no),
  596. },
  597. BorshToken::Uint {
  598. width: 64,
  599. value: BigInt::from(102 + i + array_no * 500),
  600. },
  601. ])
  602. .accounts(vec![("dataAccount", data_account)])
  603. .call()
  604. .unwrap();
  605. assert_eq!(
  606. returns,
  607. BorshToken::Uint {
  608. width: 64,
  609. value: BigInt::from(300331 + i)
  610. },
  611. );
  612. }
  613. }
  614. let returns = vm
  615. .function("map")
  616. .arguments(&[
  617. BorshToken::Uint {
  618. width: 256,
  619. value: BigInt::zero(),
  620. },
  621. BorshToken::Uint {
  622. width: 64,
  623. value: BigInt::from(101u8),
  624. },
  625. ])
  626. .accounts(vec![("dataAccount", data_account)])
  627. .call()
  628. .unwrap();
  629. assert_eq!(
  630. returns,
  631. BorshToken::Uint {
  632. width: 64,
  633. value: BigInt::zero()
  634. }
  635. );
  636. vm.function("rm")
  637. .arguments(&[
  638. BorshToken::Uint {
  639. width: 64,
  640. value: BigInt::zero(),
  641. },
  642. BorshToken::Uint {
  643. width: 64,
  644. value: BigInt::from(104u8),
  645. },
  646. ])
  647. .accounts(vec![("dataAccount", data_account)])
  648. .call();
  649. for i in 0..10 {
  650. let returns = vm
  651. .function("map")
  652. .arguments(&[
  653. BorshToken::Uint {
  654. width: 256,
  655. value: BigInt::zero(),
  656. },
  657. BorshToken::Uint {
  658. width: 64,
  659. value: BigInt::from(102 + i),
  660. },
  661. ])
  662. .accounts(vec![("dataAccount", data_account)])
  663. .call()
  664. .unwrap();
  665. if 102 + i != 104 {
  666. assert_eq!(
  667. returns,
  668. BorshToken::Uint {
  669. width: 64,
  670. value: BigInt::from(300331 + i)
  671. },
  672. );
  673. } else {
  674. assert_eq!(
  675. returns,
  676. BorshToken::Uint {
  677. width: 64,
  678. value: BigInt::zero()
  679. }
  680. );
  681. }
  682. }
  683. let returns = vm
  684. .function("length")
  685. .accounts(vec![("dataAccount", data_account)])
  686. .call()
  687. .unwrap();
  688. assert_eq!(
  689. returns,
  690. BorshToken::Uint {
  691. width: 64,
  692. value: BigInt::from(2u8)
  693. }
  694. );
  695. vm.function("pop")
  696. .accounts(vec![("dataAccount", data_account)])
  697. .call();
  698. let returns = vm
  699. .function("length")
  700. .accounts(vec![("dataAccount", data_account)])
  701. .call()
  702. .unwrap();
  703. assert_eq!(
  704. returns,
  705. BorshToken::Uint {
  706. width: 64,
  707. value: BigInt::one()
  708. }
  709. );
  710. vm.function("pop")
  711. .accounts(vec![("dataAccount", data_account)])
  712. .call();
  713. let returns = vm
  714. .function("length")
  715. .accounts(vec![("dataAccount", data_account)])
  716. .call()
  717. .unwrap();
  718. assert_eq!(
  719. returns,
  720. BorshToken::Uint {
  721. width: 64,
  722. value: BigInt::zero()
  723. }
  724. );
  725. let returns = vm
  726. .function("number")
  727. .accounts(vec![("dataAccount", data_account)])
  728. .call()
  729. .unwrap();
  730. assert_eq!(
  731. returns,
  732. BorshToken::Int {
  733. width: 64,
  734. value: BigInt::from(2147483647u64)
  735. }
  736. );
  737. }
  738. #[test]
  739. fn mapping_in_struct_in_dynamic_array() {
  740. let mut vm = build_solidity(
  741. r#"
  742. contract foo {
  743. struct A {
  744. mapping(uint256 => uint256) a;
  745. }
  746. A[] private map;
  747. int64 public number;
  748. function set(uint64 array_no, uint64 index, uint64 val) public {
  749. map[array_no].a[index] = val;
  750. }
  751. function get(uint64 array_no, uint64 index) public returns (uint256) {
  752. return map[array_no].a[index];
  753. }
  754. function rm(uint64 array_no, uint64 index) public {
  755. delete map[array_no].a[index];
  756. }
  757. function push() public {
  758. map.push();
  759. }
  760. function pop() public {
  761. map.pop();
  762. }
  763. function setNumber(int64 x) public {
  764. number = x;
  765. }
  766. }"#,
  767. );
  768. let data_account = vm.initialize_data_account();
  769. vm.function("new")
  770. .accounts(vec![("dataAccount", data_account)])
  771. .call();
  772. vm.function("setNumber")
  773. .arguments(&[BorshToken::Int {
  774. width: 64,
  775. value: BigInt::from(2147483647),
  776. }])
  777. .accounts(vec![("dataAccount", data_account)])
  778. .call();
  779. vm.function("push")
  780. .accounts(vec![("dataAccount", data_account)])
  781. .call();
  782. vm.function("push")
  783. .accounts(vec![("dataAccount", data_account)])
  784. .call();
  785. for array_no in 0..2 {
  786. for i in 0..10 {
  787. vm.function("set")
  788. .arguments(&[
  789. BorshToken::Uint {
  790. width: 64,
  791. value: BigInt::from(array_no),
  792. },
  793. BorshToken::Uint {
  794. width: 64,
  795. value: BigInt::from(102 + i + array_no * 500),
  796. },
  797. BorshToken::Uint {
  798. width: 64,
  799. value: BigInt::from(300331 + i),
  800. },
  801. ])
  802. .accounts(vec![("dataAccount", data_account)])
  803. .call();
  804. }
  805. }
  806. for array_no in 0..2 {
  807. for i in 0..10 {
  808. let returns = vm
  809. .function("get")
  810. .arguments(&[
  811. BorshToken::Uint {
  812. width: 64,
  813. value: BigInt::from(array_no),
  814. },
  815. BorshToken::Uint {
  816. width: 64,
  817. value: BigInt::from(102 + i + array_no * 500),
  818. },
  819. ])
  820. .accounts(vec![("dataAccount", data_account)])
  821. .call()
  822. .unwrap();
  823. assert_eq!(
  824. returns,
  825. BorshToken::Uint {
  826. width: 256,
  827. value: BigInt::from(300331 + i)
  828. },
  829. );
  830. }
  831. }
  832. let returns = vm
  833. .function("get")
  834. .arguments(&[
  835. BorshToken::Uint {
  836. width: 64,
  837. value: BigInt::zero(),
  838. },
  839. BorshToken::Uint {
  840. width: 64,
  841. value: BigInt::from(101u8),
  842. },
  843. ])
  844. .accounts(vec![("dataAccount", data_account)])
  845. .call()
  846. .unwrap();
  847. assert_eq!(
  848. returns,
  849. BorshToken::Uint {
  850. width: 256,
  851. value: BigInt::zero(),
  852. },
  853. );
  854. vm.function("rm")
  855. .arguments(&[
  856. BorshToken::Uint {
  857. width: 64,
  858. value: BigInt::zero(),
  859. },
  860. BorshToken::Uint {
  861. width: 64,
  862. value: BigInt::from(104u8),
  863. },
  864. ])
  865. .accounts(vec![("dataAccount", data_account)])
  866. .call();
  867. for i in 0..10 {
  868. let returns = vm
  869. .function("get")
  870. .arguments(&[
  871. BorshToken::Uint {
  872. width: 64,
  873. value: BigInt::zero(),
  874. },
  875. BorshToken::Uint {
  876. width: 64,
  877. value: BigInt::from(102 + i),
  878. },
  879. ])
  880. .accounts(vec![("dataAccount", data_account)])
  881. .call()
  882. .unwrap();
  883. if 102 + i != 104 {
  884. assert_eq!(
  885. returns,
  886. BorshToken::Uint {
  887. width: 256,
  888. value: BigInt::from(300331 + i)
  889. }
  890. );
  891. } else {
  892. assert_eq!(
  893. returns,
  894. BorshToken::Uint {
  895. width: 256,
  896. value: BigInt::zero()
  897. }
  898. );
  899. }
  900. }
  901. vm.function("pop")
  902. .accounts(vec![("dataAccount", data_account)])
  903. .call();
  904. vm.function("pop")
  905. .accounts(vec![("dataAccount", data_account)])
  906. .call();
  907. let returns = vm
  908. .function("number")
  909. .accounts(vec![("dataAccount", data_account)])
  910. .call()
  911. .unwrap();
  912. assert_eq!(
  913. returns,
  914. BorshToken::Int {
  915. width: 64,
  916. value: BigInt::from(2147483647u64),
  917. }
  918. );
  919. }
  920. #[test]
  921. fn mapping_delete() {
  922. let mut vm = build_solidity(
  923. r#"
  924. contract DeleteTest {
  925. struct data_struct {
  926. address addr1;
  927. address addr2;
  928. }
  929. mapping(uint => data_struct) example;
  930. function addData(address sender) public {
  931. data_struct dt = data_struct({addr1: address(this), addr2: sender});
  932. uint id = 1;
  933. example[id] = dt;
  934. }
  935. function deltest() external {
  936. uint id = 1;
  937. delete example[id];
  938. }
  939. function get() public view returns (data_struct calldata) {
  940. uint id = 1;
  941. return example[id];
  942. }
  943. }
  944. "#,
  945. );
  946. let sender = account_new();
  947. let data_account = vm.initialize_data_account();
  948. vm.function("new")
  949. .accounts(vec![("dataAccount", data_account)])
  950. .call();
  951. let _ = vm
  952. .function("addData")
  953. .arguments(&[BorshToken::Address(sender)])
  954. .accounts(vec![("dataAccount", data_account)])
  955. .call();
  956. let _ = vm
  957. .function("deltest")
  958. .accounts(vec![("dataAccount", data_account)])
  959. .call();
  960. let returns = vm
  961. .function("get")
  962. .accounts(vec![("dataAccount", data_account)])
  963. .call()
  964. .unwrap();
  965. assert_eq!(
  966. returns,
  967. BorshToken::Tuple(vec![
  968. BorshToken::Address([
  969. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  970. 0, 0, 0, 0
  971. ]),
  972. BorshToken::Address([
  973. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  974. 0, 0, 0, 0
  975. ])
  976. ]),
  977. );
  978. }
  979. #[test]
  980. fn mapping_within_struct() {
  981. let mut vm = build_solidity(
  982. r#"
  983. contract CrowdFunding {
  984. struct Funder {
  985. address addr;
  986. uint amount;
  987. }
  988. struct Campaign {
  989. mapping(uint => Funder)[2] arr_mp;
  990. mapping (uint => Funder) funders;
  991. }
  992. uint numCampaigns;
  993. mapping (uint => Campaign) campaigns;
  994. function newCampaign(address sender) public returns (uint campaignID) {
  995. campaignID = numCampaigns++;
  996. Campaign storage _campaign = campaigns[campaignID];
  997. _campaign.funders[0] = Funder(sender, 100);
  998. _campaign.arr_mp[1][0] = Funder(sender, 105);
  999. }
  1000. function getAmt() public view returns (uint) {
  1001. Campaign storage _campaign = campaigns[numCampaigns - 1];
  1002. return _campaign.funders[0].amount;
  1003. }
  1004. function getArrAmt() public view returns (uint) {
  1005. Campaign storage _campaign = campaigns[numCampaigns - 1];
  1006. return _campaign.arr_mp[1][0].amount;
  1007. }
  1008. }
  1009. "#,
  1010. );
  1011. let sender = account_new();
  1012. let data_account = vm.initialize_data_account();
  1013. vm.function("new")
  1014. .accounts(vec![("dataAccount", data_account)])
  1015. .call();
  1016. let ret = vm
  1017. .function("newCampaign")
  1018. .arguments(&[BorshToken::Address(sender)])
  1019. .accounts(vec![("dataAccount", data_account)])
  1020. .call()
  1021. .unwrap();
  1022. assert_eq!(
  1023. ret,
  1024. BorshToken::Uint {
  1025. width: 256,
  1026. value: BigInt::zero(),
  1027. }
  1028. );
  1029. let ret = vm
  1030. .function("getAmt")
  1031. .accounts(vec![("dataAccount", data_account)])
  1032. .call()
  1033. .unwrap();
  1034. assert_eq!(
  1035. ret,
  1036. BorshToken::Uint {
  1037. width: 256,
  1038. value: BigInt::from(100u8),
  1039. }
  1040. );
  1041. let ret = vm
  1042. .function("getArrAmt")
  1043. .accounts(vec![("dataAccount", data_account)])
  1044. .call()
  1045. .unwrap();
  1046. assert_eq!(
  1047. ret,
  1048. BorshToken::Uint {
  1049. width: 256,
  1050. value: BigInt::from(105u8),
  1051. }
  1052. );
  1053. }