structs.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. // SPDX-License-Identifier: Apache-2.0
  2. use parity_scale_codec::{Decode, Encode};
  3. use serde_derive::Deserialize;
  4. use crate::build_solidity;
  5. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  6. struct Val32(u32);
  7. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  8. struct Val8(u8);
  9. #[test]
  10. fn struct_members() {
  11. let mut runtime = build_solidity(
  12. r#"
  13. pragma solidity 0;
  14. pragma experimental ABIEncoderV2;
  15. contract test_struct_parsing {
  16. struct foo {
  17. bool x;
  18. uint32 y;
  19. bytes31 d;
  20. }
  21. function test() public {
  22. foo f;
  23. f.x = true;
  24. f.y = 64;
  25. assert(f.x == true);
  26. assert(f.y == 64);
  27. assert(f.d.length == 31);
  28. foo f2 = foo(false, 32168, hex"DEAD");
  29. assert(f2.x == false);
  30. assert(f2.y == 32168);
  31. assert(f2.d == hex"dead");
  32. foo f3 = foo({ x: true, y: 102, d: hex"00DEAD" });
  33. assert(f3.x == true);
  34. assert(f3.y == 102);
  35. assert(f3.d == hex"00dead");
  36. }
  37. }"#,
  38. );
  39. runtime.function("test", Vec::new());
  40. }
  41. #[test]
  42. fn structs_as_ref_args() {
  43. let mut runtime = build_solidity(
  44. r##"
  45. contract test_struct_parsing {
  46. struct foo {
  47. bool x;
  48. uint32 y;
  49. }
  50. function func(foo f) private {
  51. // assigning to f members dereferences f
  52. f.x = true;
  53. f.y = 64;
  54. // assigning to f changes the reference
  55. f = foo({ x: false, y: 256 });
  56. // f no longer point to f in caller function
  57. f.x = false;
  58. f.y = 98123;
  59. }
  60. function test() public {
  61. foo f = foo(false, 2);
  62. func(f);
  63. assert(f.x == true);
  64. assert(f.y == 64);
  65. }
  66. }"##,
  67. );
  68. runtime.function("test", Vec::new());
  69. }
  70. #[test]
  71. fn structs_encode() {
  72. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  73. struct Foo {
  74. f1: [u8; 3],
  75. f2: bool,
  76. }
  77. let mut runtime = build_solidity(
  78. r#"
  79. contract test_struct_parsing {
  80. struct foo {
  81. bytes3 f1;
  82. bool f2;
  83. }
  84. function test(foo f) public {
  85. assert(f.f1 == "ABC");
  86. assert(f.f2 == true);
  87. }
  88. }"#,
  89. );
  90. runtime.function(
  91. "test",
  92. Foo {
  93. f1: [0x41, 0x42, 0x43],
  94. f2: true,
  95. }
  96. .encode(),
  97. );
  98. }
  99. #[test]
  100. fn structs_decode() {
  101. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  102. struct Foo {
  103. f1: [u8; 3],
  104. f2: i32,
  105. }
  106. let mut runtime = build_solidity(
  107. r#"
  108. contract test_struct_parsing {
  109. struct foo {
  110. bytes3 f1;
  111. int32 f2;
  112. }
  113. function test() public returns (foo) {
  114. foo f;
  115. f.f1 = hex"f33ec3";
  116. f.f2 = 0xfd7f;
  117. return f;
  118. }
  119. }"#,
  120. );
  121. runtime.function("test", Vec::new());
  122. assert_eq!(
  123. runtime.output(),
  124. Foo {
  125. f1: [0xf3, 0x3e, 0xc3],
  126. f2: 0xfd7f,
  127. }
  128. .encode(),
  129. );
  130. // allocate an array of structs. On dereference, the
  131. // struct elements are allocated. Here we are testing
  132. // the allocation and also that the abi encoder can
  133. // an struct when the pointer is still null
  134. let mut runtime = build_solidity(
  135. r#"
  136. contract test_struct_parsing {
  137. struct foo {
  138. bytes3 f1;
  139. int32 f2;
  140. }
  141. function test() public returns (foo[]) {
  142. foo[] f = new foo[](3);
  143. f[1].f1 = hex"f33ec3";
  144. f[1].f2 = 0xfd7f;
  145. return f;
  146. }
  147. }"#,
  148. );
  149. runtime.constructor(0, Vec::new());
  150. runtime.function("test", Vec::new());
  151. assert_eq!(
  152. runtime.output(),
  153. vec![
  154. Foo {
  155. f1: [0, 0, 0],
  156. f2: 0,
  157. },
  158. Foo {
  159. f1: [0xf3, 0x3e, 0xc3],
  160. f2: 0xfd7f,
  161. },
  162. Foo {
  163. f1: [0, 0, 0],
  164. f2: 0,
  165. },
  166. ]
  167. .encode(),
  168. );
  169. #[derive(Debug, PartialEq, Eq, Encode, Decode, Deserialize)]
  170. struct Foo2 {
  171. f1: [u8; 3],
  172. f2: i32,
  173. f3: String,
  174. f4: Vec<i64>,
  175. f5: [bool; 4],
  176. }
  177. let mut runtime = build_solidity(
  178. r##"
  179. contract test_struct_parsing {
  180. struct foo {
  181. bytes3 f1;
  182. int32 f2;
  183. string f3;
  184. int64[] f4;
  185. bool[4] f5;
  186. }
  187. function test() public returns (foo[] f) {
  188. f = new foo[](1);
  189. }
  190. function test_zero() public returns (foo[] f) { }
  191. }"##,
  192. );
  193. runtime.constructor(0, Vec::new());
  194. runtime.function("test", Vec::new());
  195. let mut output: &[u8] = &runtime.output();
  196. assert_eq!(
  197. Vec::<Foo2>::decode(&mut output).expect("decode failed"),
  198. vec![Foo2 {
  199. f1: [0, 0, 0],
  200. f2: 0,
  201. f3: String::from(""),
  202. f4: Vec::new(),
  203. f5: [false; 4],
  204. }]
  205. );
  206. runtime.function("test_zero", Vec::new());
  207. let mut output: &[u8] = &runtime.output();
  208. assert_eq!(
  209. Vec::<Foo2>::decode(&mut output).expect("decode failed"),
  210. vec![]
  211. );
  212. }
  213. #[test]
  214. fn struct_in_struct() {
  215. let mut runtime = build_solidity(
  216. r#"
  217. pragma solidity 0;
  218. contract struct_in_struct {
  219. struct foo {
  220. bool x;
  221. uint32 y;
  222. }
  223. struct bar {
  224. address a;
  225. bytes7 b;
  226. foo c;
  227. }
  228. function test() public pure returns (bytes7) {
  229. bar memory f = bar({ a: address(0), b: hex"fe", c: foo({ x: true, y: 102 }) });
  230. foo memory m = foo(false, 50);
  231. f.c = m;
  232. f.c.y = 300;
  233. return f.b;
  234. }
  235. }"#,
  236. );
  237. runtime.function("test", Vec::new());
  238. }
  239. #[test]
  240. fn structs_in_structs_decode() {
  241. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  242. struct Foo {
  243. f1: [u8; 3],
  244. f2: i32,
  245. }
  246. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  247. struct Bar {
  248. a: bool,
  249. b: Foo,
  250. c: Foo,
  251. }
  252. let mut runtime = build_solidity(
  253. r#"
  254. contract test_struct_parsing {
  255. struct foo {
  256. bytes3 f1;
  257. int32 f2;
  258. }
  259. struct bar {
  260. bool a;
  261. foo b;
  262. foo c;
  263. }
  264. function test() public returns (bar) {
  265. bar f = bar({ a: true, b: foo({ f1: hex"c30000", f2: 0xff7f}), c: foo({ f1: hex"f7f6f5", f2: 0x4002 })});
  266. return f;
  267. }
  268. }"#,
  269. );
  270. runtime.function("test", Vec::new());
  271. assert_eq!(
  272. runtime.output(),
  273. Bar {
  274. a: true,
  275. b: Foo {
  276. f1: [0xc3, 0x00, 0x00],
  277. f2: 0xff7f,
  278. },
  279. c: Foo {
  280. f1: [0xf7, 0xf6, 0xf5],
  281. f2: 0x4002,
  282. }
  283. }
  284. .encode(),
  285. );
  286. }
  287. #[test]
  288. fn structs_in_structs_encode() {
  289. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  290. struct Foo {
  291. f1: [u8; 3],
  292. f2: i32,
  293. }
  294. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  295. struct Bar {
  296. a: bool,
  297. b: Foo,
  298. c: Foo,
  299. }
  300. let mut runtime = build_solidity(
  301. r#"
  302. contract test_struct_parsing {
  303. struct foo {
  304. bytes3 f1;
  305. int32 f2;
  306. }
  307. function test(other.bar f) public {
  308. assert(f.c.f2 == 0x4002);
  309. assert(f.b.f1 == hex"c30000");
  310. }
  311. }
  312. abstract contract other {
  313. struct bar {
  314. bool a;
  315. test_struct_parsing.foo b;
  316. test_struct_parsing.foo c;
  317. }
  318. }"#,
  319. );
  320. runtime.function(
  321. "test",
  322. Bar {
  323. a: true,
  324. b: Foo {
  325. f1: [0xc3, 0x00, 0x00],
  326. f2: 0xff7f,
  327. },
  328. c: Foo {
  329. f1: [0xf7, 0xf6, 0xf5],
  330. f2: 0x4002,
  331. },
  332. }
  333. .encode(),
  334. );
  335. }
  336. #[test]
  337. fn struct_storage_to_memory() {
  338. let mut runtime = build_solidity(
  339. r#"
  340. contract test_struct_parsing {
  341. struct foo {
  342. bytes3 f1;
  343. int64 f2;
  344. }
  345. foo bar;
  346. constructor() public {
  347. bar.f1 = hex"123456";
  348. bar.f2 = 0x0123456789abcdef;
  349. }
  350. function test() public {
  351. foo f = bar;
  352. assert(f.f1 == hex"123456");
  353. assert(f.f2 == 81985529216486895);
  354. }
  355. }"#,
  356. );
  357. runtime.constructor(0, Vec::new());
  358. runtime.function("test", Vec::new());
  359. }
  360. #[test]
  361. fn return_from_struct_storage() {
  362. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  363. struct Foo {
  364. f1: [u8; 3],
  365. f2: u32,
  366. }
  367. let mut runtime = build_solidity(
  368. r#"
  369. struct foo {
  370. bytes3 f1;
  371. uint32 f2;
  372. }
  373. contract test_struct_parsing {
  374. foo bar;
  375. constructor() public {
  376. bar.f1 = "png";
  377. bar.f2 = 0x89abcdef;
  378. }
  379. function test() public returns (foo) {
  380. return bar;
  381. }
  382. }"#,
  383. );
  384. runtime.constructor(0, Vec::new());
  385. runtime.function("test", Vec::new());
  386. assert_eq!(
  387. runtime.output(),
  388. Foo {
  389. f1: [0x70, 0x6e, 0x67],
  390. f2: 0x89ab_cdef,
  391. }
  392. .encode(),
  393. );
  394. }
  395. #[test]
  396. fn struct_in_init_return() {
  397. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  398. struct Card {
  399. value: u8,
  400. suit: u8,
  401. }
  402. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  403. struct Hand {
  404. card1: Card,
  405. card2: Card,
  406. card3: Card,
  407. card4: Card,
  408. card5: Card,
  409. }
  410. let mut runtime = build_solidity(
  411. r#"
  412. enum suit { club, diamonds, hearts, spades }
  413. enum value { two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace }
  414. struct card {
  415. value v;
  416. suit s;
  417. }
  418. contract structs {
  419. card card1 = card({ s: suit.hearts, v: value.two });
  420. card card2 = card({ s: suit.diamonds, v: value.three });
  421. card card3 = card({ s: suit.club, v: value.four });
  422. card card4 = card({ s: suit.diamonds, v: value.ten });
  423. card card5 = card({ s: suit.hearts, v: value.jack });
  424. function test() public {
  425. assert(card1.s == suit.hearts);
  426. assert(card1.v == value.two);
  427. assert(card2.s == suit.diamonds);
  428. assert(card2.v == value.three);
  429. assert(card3.s == suit.club);
  430. assert(card3.v == value.four);
  431. assert(card4.s == suit.diamonds);
  432. assert(card4.v == value.ten);
  433. assert(card5.s == suit.hearts);
  434. assert(card5.v == value.jack);
  435. }
  436. }"#,
  437. );
  438. runtime.constructor(0, Vec::new());
  439. runtime.function("test", Vec::new());
  440. }
  441. #[test]
  442. fn struct_struct_in_init_and_return() {
  443. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  444. struct Card {
  445. v: u8,
  446. s: u8,
  447. }
  448. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  449. struct Hand {
  450. card1: Card,
  451. card2: Card,
  452. card3: Card,
  453. card4: Card,
  454. card5: Card,
  455. }
  456. let mut runtime = build_solidity(
  457. r#"
  458. contract structs {
  459. enum suit { club, diamonds, hearts, spades }
  460. enum value { two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace }
  461. struct card {
  462. value v;
  463. suit s;
  464. }
  465. struct hand {
  466. card card1;
  467. card card2;
  468. card card3;
  469. card card4;
  470. card card5;
  471. }
  472. hand h = hand({
  473. card1: card({ s: suit.hearts, v: value.two }),
  474. card2: card({ s: suit.diamonds, v: value.three }),
  475. card3: card({ s: suit.club, v: value.four }),
  476. card4: card({ s: suit.diamonds, v: value.ten }),
  477. card5: card({ s: suit.hearts, v: value.jack })
  478. });
  479. function return_struct_from_storage(hand storage n) private returns (hand) {
  480. return n;
  481. }
  482. function test() public {
  483. hand l = return_struct_from_storage(h);
  484. assert(l.card1.s == suit.hearts);
  485. assert(l.card1.v == value.two);
  486. assert(l.card2.s == suit.diamonds);
  487. assert(l.card2.v == value.three);
  488. assert(l.card3.s == suit.club);
  489. assert(l.card3.v == value.four);
  490. assert(l.card4.s == suit.diamonds);
  491. assert(l.card4.v == value.ten);
  492. assert(l.card5.s == suit.hearts);
  493. assert(l.card5.v == value.jack);
  494. }
  495. }
  496. "#,
  497. );
  498. runtime.constructor(0, Vec::new());
  499. runtime.function("test", Vec::new());
  500. }
  501. #[test]
  502. fn encode_decode_bytes_in_field() {
  503. #[derive(Debug, PartialEq, Eq, Encode, Decode)]
  504. struct Foo([u8; 4]);
  505. let mut runtime = build_solidity(
  506. r#"
  507. contract encode_decode_bytes_in_field {
  508. struct foo { bytes4 f1; }
  509. function test() public pure returns(foo) {
  510. foo f = abi.decode(hex"41424344", (foo));
  511. assert(abi.encode(f) == hex"41424344");
  512. return f;
  513. }
  514. }"#,
  515. );
  516. runtime.function("test", vec![]);
  517. assert_eq!(runtime.output(), Foo([0x41, 0x42, 0x43, 0x44]).encode())
  518. }