uniswapv2_pair.rs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. // SPDX-License-Identifier: Apache-2.0
  2. use std::ops::Mul;
  3. use contract_transcode::ContractMessageTranscoder;
  4. use hex::FromHex;
  5. use parity_scale_codec::{Decode, DecodeAll, Encode, Input};
  6. use rand::Rng;
  7. use sp_core::{
  8. crypto::{AccountId32, Ss58Codec},
  9. hexdisplay::AsBytesRef,
  10. keccak_256, U256,
  11. };
  12. use crate::{Contract, DeployContract, Execution, ReadContract, WriteContract, API};
  13. #[ignore = "trapped when transfer liquidity"]
  14. #[tokio::test]
  15. async fn mint() -> anyhow::Result<()> {
  16. let api = API::new().await?;
  17. let w = MockWorld::init(&api).await?;
  18. let min_liquidity: U256 = U256::from(1000_u32);
  19. w.token_0
  20. .call(
  21. &api,
  22. sp_keyring::AccountKeyring::Alice,
  23. 0,
  24. &|t: &ContractMessageTranscoder| {
  25. let mut s = keccak_256(b"transfer(address,uint)")[..4].to_vec();
  26. w.pair.address.clone().unwrap().encode_to(&mut s);
  27. U256::from(10_u8).pow(18_u8.into()).encode_to(&mut s);
  28. s
  29. },
  30. )
  31. .await?;
  32. w.token_1
  33. .call(
  34. &api,
  35. sp_keyring::AccountKeyring::Alice,
  36. 0,
  37. &|t: &ContractMessageTranscoder| {
  38. let mut s = keccak_256(b"transfer(address,uint)")[..4].to_vec();
  39. w.pair.address.clone().unwrap().encode_to(&mut s);
  40. U256::from(10_u8)
  41. .pow(18_u8.into())
  42. .mul(U256::from(4_u8))
  43. .encode_to(&mut s);
  44. s
  45. },
  46. )
  47. .await?;
  48. let expected_liquidity = U256::from(10_u8).pow(18_u8.into()).mul(U256::from(2_u8));
  49. w.pair
  50. .call(
  51. &api,
  52. sp_keyring::AccountKeyring::Alice,
  53. 0,
  54. &|t: &ContractMessageTranscoder| {
  55. t.encode::<_, String>(
  56. "mint",
  57. [format!(
  58. "0x{}",
  59. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  60. )],
  61. )
  62. .unwrap()
  63. },
  64. )
  65. .await?;
  66. let total_supply = w
  67. .pair
  68. .try_call(
  69. &api,
  70. sp_keyring::AccountKeyring::Alice,
  71. 0,
  72. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  73. )
  74. .await
  75. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  76. assert_eq!(expected_liquidity, total_supply);
  77. let balance = w
  78. .pair
  79. .try_call(
  80. &api,
  81. sp_keyring::AccountKeyring::Alice,
  82. 0,
  83. &|t: &ContractMessageTranscoder| {
  84. t.encode::<_, String>(
  85. "balanceOf",
  86. [format!(
  87. "0x{}",
  88. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  89. )],
  90. )
  91. .unwrap()
  92. },
  93. )
  94. .await
  95. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  96. assert_eq!(balance, expected_liquidity - min_liquidity);
  97. let balance_0 = w
  98. .token_0
  99. .try_call(
  100. &api,
  101. sp_keyring::AccountKeyring::Alice,
  102. 0,
  103. &|t: &ContractMessageTranscoder| {
  104. t.encode::<_, String>(
  105. "balanceOf",
  106. [format!(
  107. "0x{}",
  108. hex::encode(w.pair.address.as_ref().unwrap())
  109. )],
  110. )
  111. .unwrap()
  112. },
  113. )
  114. .await
  115. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  116. assert_eq!(balance_0, U256::from(10_u8).pow(18_u8.into()));
  117. let balance_1 = w
  118. .token_1
  119. .try_call(
  120. &api,
  121. sp_keyring::AccountKeyring::Alice,
  122. 0,
  123. &|t: &ContractMessageTranscoder| {
  124. t.encode::<_, String>(
  125. "balanceOf",
  126. [format!(
  127. "0x{}",
  128. hex::encode(w.pair.address.as_ref().unwrap())
  129. )],
  130. )
  131. .unwrap()
  132. },
  133. )
  134. .await
  135. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  136. assert_eq!(
  137. balance_1,
  138. U256::from(10_u8).pow(18_u8.into()).mul(U256::from(4_u8))
  139. );
  140. let (r0, r1, block) = w
  141. .pair
  142. .try_call(
  143. &api,
  144. sp_keyring::AccountKeyring::Alice,
  145. 0,
  146. &|t: &ContractMessageTranscoder| t.encode::<_, String>("getReserves", []).unwrap(),
  147. )
  148. .await
  149. .and_then(|v| <(u128, u128, u32)>::decode(&mut &v[..]).map_err(Into::into))?;
  150. assert_eq!(U256::from(r0), U256::from(10_u8).pow(18_u8.into()));
  151. assert_eq!(
  152. U256::from(r1),
  153. U256::from(10_u8).pow(18_u8.into()).mul(U256::from(4_u8))
  154. );
  155. Ok(())
  156. }
  157. #[ignore = "trapped when adding liquidity"]
  158. #[tokio::test]
  159. async fn swap_token0() -> anyhow::Result<()> {
  160. let api = API::new().await?;
  161. let token0_amount = U256::from(10_u8)
  162. .pow(U256::from(18_u8))
  163. .mul(U256::from(5_u8));
  164. let token1_amount = U256::from(10_u8).pow(U256::from(19_u8));
  165. let w = MockWorld::init(&api).await?;
  166. let min_liquidity: U256 = U256::from(1000_u32);
  167. w.add_liquitity(&api, &token0_amount, &token1_amount)
  168. .await?;
  169. let swap_amount = U256::from(10_u8).pow(18_u8.into());
  170. let expected_output = U256::from_dec_str("1662497915624478906")?;
  171. w.token_0
  172. .call(
  173. &api,
  174. sp_keyring::AccountKeyring::Alice,
  175. 0,
  176. &|t: &ContractMessageTranscoder| {
  177. let mut s = t
  178. .encode::<_, String>(
  179. "transfer",
  180. [format!(
  181. "0x{}",
  182. hex::encode(w.pair.address.as_ref().unwrap())
  183. )],
  184. )
  185. .unwrap();
  186. swap_amount.encode_to(&mut s);
  187. s
  188. },
  189. )
  190. .await?;
  191. w.pair
  192. .call(
  193. &api,
  194. sp_keyring::AccountKeyring::Alice,
  195. 0,
  196. &|t: &ContractMessageTranscoder| {
  197. let mut s = t.encode::<_, String>("swap", []).unwrap();
  198. (
  199. U256::zero(),
  200. expected_output,
  201. sp_keyring::AccountKeyring::Alice.to_account_id(),
  202. "",
  203. )
  204. .encode_to(&mut s);
  205. s
  206. },
  207. )
  208. .await?;
  209. let out = w
  210. .pair
  211. .try_call(
  212. &api,
  213. sp_keyring::AccountKeyring::Alice,
  214. 0,
  215. &|t: &ContractMessageTranscoder| t.encode::<_, String>("getReserves", []).unwrap(),
  216. )
  217. .await
  218. .and_then(|v| {
  219. let t = &w.pair.transcoder;
  220. <(u128, u128, u32)>::decode(&mut &v[..]).map_err(Into::into)
  221. })?;
  222. assert_eq!(U256::from(out.0), token0_amount + swap_amount);
  223. assert_eq!(U256::from(out.1), token1_amount - expected_output);
  224. let bal_0 = w
  225. .token_0
  226. .try_call(
  227. &api,
  228. sp_keyring::AccountKeyring::Alice,
  229. 0,
  230. &|t: &ContractMessageTranscoder| {
  231. t.encode::<_, String>(
  232. "balanceOf",
  233. [format!(
  234. "0x{}",
  235. hex::encode(w.pair.address.as_ref().unwrap())
  236. )],
  237. )
  238. .unwrap()
  239. },
  240. )
  241. .await
  242. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  243. assert_eq!(bal_0, token0_amount + swap_amount);
  244. let bal_1 = w
  245. .token_1
  246. .try_call(
  247. &api,
  248. sp_keyring::AccountKeyring::Alice,
  249. 0,
  250. &|t: &ContractMessageTranscoder| {
  251. t.encode::<_, String>(
  252. "balanceOf",
  253. [format!(
  254. "0x{}",
  255. hex::encode(w.pair.address.as_ref().unwrap())
  256. )],
  257. )
  258. .unwrap()
  259. },
  260. )
  261. .await
  262. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  263. assert_eq!(bal_1, token1_amount - expected_output);
  264. let supply_0 = w
  265. .token_0
  266. .try_call(
  267. &api,
  268. sp_keyring::AccountKeyring::Alice,
  269. 0,
  270. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  271. )
  272. .await
  273. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  274. let supply_1 = w
  275. .token_1
  276. .try_call(
  277. &api,
  278. sp_keyring::AccountKeyring::Alice,
  279. 0,
  280. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  281. )
  282. .await
  283. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  284. let wallet_balance_0 = w
  285. .token_0
  286. .try_call(
  287. &api,
  288. sp_keyring::AccountKeyring::Alice,
  289. 0,
  290. &|t: &ContractMessageTranscoder| {
  291. t.encode::<_, String>(
  292. "balanceOf",
  293. [format!(
  294. "0x{}",
  295. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  296. )],
  297. )
  298. .unwrap()
  299. },
  300. )
  301. .await
  302. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  303. let wallet_balance_1 = w
  304. .token_1
  305. .try_call(
  306. &api,
  307. sp_keyring::AccountKeyring::Alice,
  308. 0,
  309. &|t: &ContractMessageTranscoder| {
  310. t.encode::<_, String>(
  311. "balanceOf",
  312. [format!(
  313. "0x{}",
  314. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  315. )],
  316. )
  317. .unwrap()
  318. },
  319. )
  320. .await
  321. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  322. assert_eq!(wallet_balance_0, supply_0 - token0_amount - swap_amount,);
  323. assert_eq!(wallet_balance_1, supply_1 - token1_amount + expected_output);
  324. Ok(())
  325. }
  326. #[ignore = "trapped when adding liquidity"]
  327. #[tokio::test]
  328. async fn swap_token1() -> anyhow::Result<()> {
  329. let api = API::new().await?;
  330. let token0_amount = U256::from(10_u8)
  331. .pow(U256::from(18_u8))
  332. .mul(U256::from(5_u8));
  333. let token1_amount = U256::from(10_u8).pow(U256::from(19_u8));
  334. let w = MockWorld::init(&api).await?;
  335. let min_liquidity: U256 = U256::from(1000_u32);
  336. w.add_liquitity(&api, &token0_amount, &token1_amount)
  337. .await?;
  338. let swap_amount = U256::from(10_u8).pow(18_u8.into());
  339. let expected_output = U256::from_dec_str("453305446940074565")?;
  340. w.token_1
  341. .call(
  342. &api,
  343. sp_keyring::AccountKeyring::Alice,
  344. 0,
  345. &|t: &ContractMessageTranscoder| {
  346. let mut s = t
  347. .encode::<_, String>(
  348. "transfer",
  349. [format!(
  350. "0x{}",
  351. hex::encode(w.pair.address.as_ref().unwrap())
  352. )],
  353. )
  354. .unwrap();
  355. swap_amount.encode_to(&mut s);
  356. s
  357. },
  358. )
  359. .await?;
  360. w.pair
  361. .call(
  362. &api,
  363. sp_keyring::AccountKeyring::Alice,
  364. 0,
  365. &|t: &ContractMessageTranscoder| {
  366. let mut s = t.encode::<_, String>("swap", []).unwrap();
  367. (
  368. expected_output,
  369. U256::zero(),
  370. sp_keyring::AccountKeyring::Alice.to_account_id(),
  371. "",
  372. )
  373. .encode_to(&mut s);
  374. s
  375. },
  376. )
  377. .await?;
  378. let out = w
  379. .pair
  380. .try_call(
  381. &api,
  382. sp_keyring::AccountKeyring::Alice,
  383. 0,
  384. &|t: &ContractMessageTranscoder| t.encode::<_, String>("getReserves", []).unwrap(),
  385. )
  386. .await
  387. .and_then(|v| <(u128, u128, u32)>::decode(&mut &v[..]).map_err(Into::into))?;
  388. assert_eq!(U256::from(out.0), token0_amount - expected_output);
  389. assert_eq!(U256::from(out.1), token1_amount + swap_amount);
  390. let bal_0 = w
  391. .token_0
  392. .try_call(
  393. &api,
  394. sp_keyring::AccountKeyring::Alice,
  395. 0,
  396. &|t: &ContractMessageTranscoder| {
  397. t.encode::<_, String>(
  398. "balanceOf",
  399. [format!(
  400. "0x{}",
  401. hex::encode(w.pair.address.as_ref().unwrap())
  402. )],
  403. )
  404. .unwrap()
  405. },
  406. )
  407. .await
  408. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  409. assert_eq!(bal_0, token0_amount - expected_output);
  410. let bal_1 = w
  411. .token_1
  412. .try_call(
  413. &api,
  414. sp_keyring::AccountKeyring::Alice,
  415. 0,
  416. &|t: &ContractMessageTranscoder| {
  417. t.encode::<_, String>(
  418. "balanceOf",
  419. [format!(
  420. "0x{}",
  421. hex::encode(w.pair.address.as_ref().unwrap())
  422. )],
  423. )
  424. .unwrap()
  425. },
  426. )
  427. .await
  428. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  429. assert_eq!(bal_1, token1_amount + swap_amount);
  430. let supply_0 = w
  431. .token_0
  432. .try_call(
  433. &api,
  434. sp_keyring::AccountKeyring::Alice,
  435. 0,
  436. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  437. )
  438. .await
  439. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  440. let supply_1 = w
  441. .token_1
  442. .try_call(
  443. &api,
  444. sp_keyring::AccountKeyring::Alice,
  445. 0,
  446. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  447. )
  448. .await
  449. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  450. let wallet_balance_0 = w
  451. .token_0
  452. .try_call(
  453. &api,
  454. sp_keyring::AccountKeyring::Alice,
  455. 0,
  456. &|t: &ContractMessageTranscoder| {
  457. t.encode::<_, String>(
  458. "balanceOf",
  459. [format!(
  460. "0x{}",
  461. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  462. )],
  463. )
  464. .unwrap()
  465. },
  466. )
  467. .await
  468. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  469. let wallet_balance_1 = w
  470. .token_1
  471. .try_call(
  472. &api,
  473. sp_keyring::AccountKeyring::Alice,
  474. 0,
  475. &|t: &ContractMessageTranscoder| {
  476. t.encode::<_, String>(
  477. "balanceOf",
  478. [format!(
  479. "0x{}",
  480. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  481. )],
  482. )
  483. .unwrap()
  484. },
  485. )
  486. .await
  487. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  488. assert_eq!(wallet_balance_0, supply_0 - token0_amount + expected_output);
  489. assert_eq!(wallet_balance_1, supply_1 - token1_amount - swap_amount);
  490. Ok(())
  491. }
  492. #[ignore = "trapped when adding liquidity"]
  493. #[tokio::test]
  494. async fn burn() -> anyhow::Result<()> {
  495. let api = API::new().await?;
  496. let w = MockWorld::init(&api).await?;
  497. let token_amount = U256::from(10_u8).pow(18_u8.into()).mul(U256::from(3_u8));
  498. w.add_liquitity(&api, &token_amount, &token_amount).await?;
  499. w.pair
  500. .call(
  501. &api,
  502. sp_keyring::AccountKeyring::Alice,
  503. 0,
  504. &|t: &ContractMessageTranscoder| {
  505. let mut s = t
  506. .encode::<_, String>(
  507. "transfer",
  508. [format!(
  509. "0x{}",
  510. hex::encode(w.pair.address.as_ref().unwrap())
  511. )],
  512. )
  513. .unwrap();
  514. (token_amount - U256::from(1000_u32)).encode_to(&mut s);
  515. s
  516. },
  517. )
  518. .await?;
  519. w.pair
  520. .call(
  521. &api,
  522. sp_keyring::AccountKeyring::Alice,
  523. 0,
  524. &|t: &ContractMessageTranscoder| {
  525. t.encode::<_, String>(
  526. "burn",
  527. [format!(
  528. "0x{}",
  529. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  530. )],
  531. )
  532. .unwrap()
  533. },
  534. )
  535. .await?;
  536. let wallet_balance_0 = w
  537. .pair
  538. .try_call(
  539. &api,
  540. sp_keyring::AccountKeyring::Alice,
  541. 0,
  542. &|t: &ContractMessageTranscoder| {
  543. t.encode::<_, String>(
  544. "balanceOf",
  545. [format!(
  546. "0x{}",
  547. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  548. )],
  549. )
  550. .unwrap()
  551. },
  552. )
  553. .await
  554. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  555. assert_eq!(wallet_balance_0, U256::zero());
  556. let pair_supply = w
  557. .pair
  558. .try_call(
  559. &api,
  560. sp_keyring::AccountKeyring::Alice,
  561. 0,
  562. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  563. )
  564. .await
  565. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  566. assert_eq!(pair_supply, U256::from(1000_u32));
  567. let pair_balance_0 = w
  568. .token_0
  569. .try_call(
  570. &api,
  571. sp_keyring::AccountKeyring::Alice,
  572. 0,
  573. &|t: &ContractMessageTranscoder| {
  574. t.encode::<_, String>(
  575. "balanceOf",
  576. [format!(
  577. "0x{}",
  578. hex::encode(w.pair.address.as_ref().unwrap())
  579. )],
  580. )
  581. .unwrap()
  582. },
  583. )
  584. .await
  585. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  586. assert_eq!(pair_balance_0, U256::from(1000_u32));
  587. let pair_balance_1 = w
  588. .token_1
  589. .try_call(
  590. &api,
  591. sp_keyring::AccountKeyring::Alice,
  592. 0,
  593. &|t: &ContractMessageTranscoder| {
  594. t.encode::<_, String>(
  595. "balanceOf",
  596. [format!(
  597. "0x{}",
  598. hex::encode(w.pair.address.as_ref().unwrap())
  599. )],
  600. )
  601. .unwrap()
  602. },
  603. )
  604. .await
  605. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  606. assert_eq!(pair_balance_1, U256::from(1000_u32));
  607. let supply_0 = w
  608. .token_0
  609. .try_call(
  610. &api,
  611. sp_keyring::AccountKeyring::Alice,
  612. 0,
  613. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  614. )
  615. .await
  616. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  617. let supply_1 = w
  618. .token_1
  619. .try_call(
  620. &api,
  621. sp_keyring::AccountKeyring::Alice,
  622. 0,
  623. &|t: &ContractMessageTranscoder| t.encode::<_, String>("totalSupply", []).unwrap(),
  624. )
  625. .await
  626. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  627. let wallet_balance_0 = w
  628. .token_0
  629. .try_call(
  630. &api,
  631. sp_keyring::AccountKeyring::Alice,
  632. 0,
  633. &|t: &ContractMessageTranscoder| {
  634. t.encode::<_, String>(
  635. "balanceOf",
  636. [format!(
  637. "0x{}",
  638. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  639. )],
  640. )
  641. .unwrap()
  642. },
  643. )
  644. .await
  645. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  646. let wallet_balance_1 = w
  647. .token_1
  648. .try_call(
  649. &api,
  650. sp_keyring::AccountKeyring::Alice,
  651. 0,
  652. &|t: &ContractMessageTranscoder| {
  653. t.encode::<_, String>(
  654. "balanceOf",
  655. [format!(
  656. "0x{}",
  657. hex::encode(sp_keyring::AccountKeyring::Alice.to_account_id())
  658. )],
  659. )
  660. .unwrap()
  661. },
  662. )
  663. .await
  664. .and_then(|v| <U256>::decode(&mut &v[..]).map_err(Into::into))?;
  665. assert_eq!(wallet_balance_0, supply_0 - U256::from(1000_u32));
  666. assert_eq!(wallet_balance_1, supply_1 - U256::from(1000_u32));
  667. Ok(())
  668. }
  669. struct MockWorld {
  670. factory: Contract,
  671. pair: Contract,
  672. token_0: Contract,
  673. token_1: Contract,
  674. }
  675. impl MockWorld {
  676. async fn init(api: &API) -> anyhow::Result<Self> {
  677. let mut factory = Contract::new("./contracts/UniswapV2Factory.contract")?;
  678. factory
  679. .deploy(
  680. api,
  681. sp_keyring::AccountKeyring::Alice,
  682. 10_u128.pow(16),
  683. &|t: &ContractMessageTranscoder| {
  684. t.encode::<_, String>(
  685. "new",
  686. [format!(
  687. "0x{}",
  688. hex::encode(&sp_keyring::AccountKeyring::Alice.to_account_id())
  689. )],
  690. )
  691. .unwrap()
  692. },
  693. )
  694. .await?;
  695. let mut pair = Contract::new("./contracts/UniswapV2Pair.contract")?;
  696. factory
  697. .upload_code(api, sp_keyring::AccountKeyring::Alice)
  698. .await?;
  699. let mut token_a = Contract::new("./contracts/UniswapV2ERC20.contract")?;
  700. token_a
  701. .deploy(
  702. api,
  703. sp_keyring::AccountKeyring::Alice,
  704. 0,
  705. &|t: &ContractMessageTranscoder| {
  706. let mut selector = t.encode::<_, String>("new", []).unwrap();
  707. U256::from(10_u8).pow(22_u8.into()).encode_to(&mut selector);
  708. selector
  709. },
  710. )
  711. .await?;
  712. let mut token_b = Contract::new("./contracts/UniswapV2ERC20.contract")?;
  713. token_b
  714. .deploy(
  715. api,
  716. sp_keyring::AccountKeyring::Alice,
  717. 0,
  718. &|t: &ContractMessageTranscoder| {
  719. let mut selector = t.encode::<_, String>("new", []).unwrap();
  720. U256::from(10_u8).pow(22_u8.into()).encode_to(&mut selector);
  721. selector
  722. },
  723. )
  724. .await?;
  725. factory
  726. .call(
  727. api,
  728. sp_keyring::AccountKeyring::Alice,
  729. 0,
  730. &|t: &ContractMessageTranscoder| {
  731. t.encode::<_, String>(
  732. "createPair",
  733. [
  734. format!("0x{}", hex::encode(token_a.address.as_ref().unwrap())),
  735. format!("0x{}", hex::encode(token_b.address.as_ref().unwrap())),
  736. ],
  737. )
  738. .unwrap()
  739. },
  740. )
  741. .await?;
  742. let pair_addr = factory
  743. .try_call(
  744. api,
  745. sp_keyring::AccountKeyring::Alice,
  746. 0,
  747. &|t: &ContractMessageTranscoder| {
  748. t.encode::<_, String>(
  749. "getPair",
  750. [
  751. format!("0x{}", hex::encode(token_a.address.as_ref().unwrap())),
  752. format!("0x{}", hex::encode(token_b.address.as_ref().unwrap())),
  753. ],
  754. )
  755. .unwrap()
  756. },
  757. )
  758. .await
  759. .and_then(|v| <AccountId32>::decode(&mut &v[..]).map_err(Into::into))?;
  760. pair = pair.from_addr(pair_addr)?;
  761. let token_0_addr = pair
  762. .try_call(
  763. api,
  764. sp_keyring::AccountKeyring::Alice,
  765. 0,
  766. &|t: &ContractMessageTranscoder| t.encode::<_, String>("token0", []).unwrap(),
  767. )
  768. .await
  769. .and_then(|v| <AccountId32>::decode(&mut &v[..]).map_err(Into::into))?;
  770. let (token_0, token_1) = if *token_a.address.as_ref().unwrap() == token_0_addr {
  771. (token_a, token_b)
  772. } else {
  773. (token_b, token_a)
  774. };
  775. Ok(Self {
  776. factory,
  777. pair,
  778. token_0,
  779. token_1,
  780. })
  781. }
  782. async fn add_liquitity(
  783. &self,
  784. api: &API,
  785. amount_a: &U256,
  786. amount_b: &U256,
  787. ) -> anyhow::Result<()> {
  788. self.token_0
  789. .call(
  790. api,
  791. sp_keyring::AccountKeyring::Alice,
  792. 0,
  793. &|t: &ContractMessageTranscoder| {
  794. let mut s = keccak_256(b"transfer(address,uint)")[..4].to_vec();
  795. self.pair.address.clone().unwrap().encode_to(&mut s);
  796. amount_a.encode_to(&mut s);
  797. s
  798. },
  799. )
  800. .await?;
  801. self.token_1
  802. .call(
  803. api,
  804. sp_keyring::AccountKeyring::Alice,
  805. 0,
  806. &|t: &ContractMessageTranscoder| {
  807. let mut s = keccak_256(b"transfer(address,uint)")[..4].to_vec();
  808. self.pair.address.clone().unwrap().encode_to(&mut s);
  809. amount_b.encode_to(&mut s);
  810. s
  811. },
  812. )
  813. .await?;
  814. self.pair
  815. .call(
  816. api,
  817. sp_keyring::AccountKeyring::Alice,
  818. 0,
  819. &|t: &ContractMessageTranscoder| {
  820. let mut s = keccak_256(b"mint(address)")[..4].to_vec();
  821. sp_keyring::AccountKeyring::Alice
  822. .to_account_id()
  823. .encode_to(&mut s);
  824. s
  825. },
  826. )
  827. .await?;
  828. Ok(())
  829. }
  830. }