pyth.cairo 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. use snforge_std::{
  2. declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, spy_events, SpyOn, EventSpy,
  3. EventFetcher, event_name_hash, Event
  4. };
  5. use pyth::pyth::{
  6. IPythDispatcher, IPythDispatcherTrait, DataSource, Event as PythEvent, PriceFeedUpdateEvent
  7. };
  8. use pyth::byte_array::{ByteArray, ByteArrayImpl};
  9. use pyth::util::{array_felt252_to_bytes31, UnwrapWithFelt252};
  10. use core::starknet::ContractAddress;
  11. use openzeppelin::token::erc20::interface::{IERC20CamelDispatcher, IERC20CamelDispatcherTrait};
  12. fn decode_event(event: @Event) -> PythEvent {
  13. if *event.keys.at(0) == event_name_hash('PriceFeedUpdate') {
  14. assert!(event.keys.len() == 3);
  15. assert!(event.data.len() == 3);
  16. let event = PriceFeedUpdateEvent {
  17. price_id: u256 {
  18. low: (*event.keys.at(1)).try_into().unwrap(),
  19. high: (*event.keys.at(2)).try_into().unwrap(),
  20. },
  21. publish_time: (*event.data.at(0)).try_into().unwrap(),
  22. price: (*event.data.at(1)).try_into().unwrap(),
  23. conf: (*event.data.at(2)).try_into().unwrap(),
  24. };
  25. PythEvent::PriceFeedUpdate(event)
  26. } else {
  27. panic!("unrecognized event")
  28. }
  29. }
  30. #[test]
  31. fn update_price_feeds_works() {
  32. let owner = 'owner'.try_into().unwrap();
  33. let user = 'user'.try_into().unwrap();
  34. let wormhole = super::wormhole::deploy_and_init(owner);
  35. let fee_contract = deploy_fee_contract(user);
  36. let pyth = deploy(
  37. owner,
  38. wormhole.contract_address,
  39. fee_contract.contract_address,
  40. 1000,
  41. array![
  42. DataSource {
  43. emitter_chain_id: 26,
  44. emitter_address: 0xe101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71,
  45. }
  46. ]
  47. );
  48. start_prank(CheatTarget::One(fee_contract.contract_address), user.try_into().unwrap());
  49. fee_contract.approve(pyth.contract_address, 10000);
  50. stop_prank(CheatTarget::One(fee_contract.contract_address));
  51. let mut spy = spy_events(SpyOn::One(pyth.contract_address));
  52. start_prank(CheatTarget::One(pyth.contract_address), user.try_into().unwrap());
  53. pyth.update_price_feeds(good_update1());
  54. stop_prank(CheatTarget::One(pyth.contract_address));
  55. spy.fetch_events();
  56. assert!(spy.events.len() == 1);
  57. let (from, event) = spy.events.at(0);
  58. assert!(from == @pyth.contract_address);
  59. let event = decode_event(event);
  60. let expected = PriceFeedUpdateEvent {
  61. price_id: 0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43,
  62. publish_time: 1712589206,
  63. price: 7192002930010,
  64. conf: 3596501465,
  65. };
  66. assert!(event == PythEvent::PriceFeedUpdate(expected));
  67. let last_price = pyth
  68. .get_price_unsafe(0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43)
  69. .unwrap_with_felt252();
  70. assert!(last_price.price == 7192002930010);
  71. assert!(last_price.conf == 3596501465);
  72. assert!(last_price.expo == -8);
  73. assert!(last_price.publish_time == 1712589206);
  74. let last_ema_price = pyth
  75. .get_ema_price_unsafe(0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43)
  76. .unwrap_with_felt252();
  77. assert!(last_ema_price.price == 7181868900000);
  78. assert!(last_ema_price.conf == 4096812700);
  79. assert!(last_ema_price.expo == -8);
  80. assert!(last_ema_price.publish_time == 1712589206);
  81. }
  82. fn deploy(
  83. owner: ContractAddress,
  84. wormhole_address: ContractAddress,
  85. fee_contract_address: ContractAddress,
  86. single_update_fee: u256,
  87. data_sources: Array<DataSource>
  88. ) -> IPythDispatcher {
  89. let mut args = array![];
  90. (owner, wormhole_address, fee_contract_address, single_update_fee).serialize(ref args);
  91. data_sources.serialize(ref args);
  92. let contract = declare("pyth");
  93. let contract_address = match contract.deploy(@args) {
  94. Result::Ok(v) => { v },
  95. Result::Err(err) => {
  96. panic(err.panic_data);
  97. 0.try_into().unwrap()
  98. },
  99. };
  100. IPythDispatcher { contract_address }
  101. }
  102. fn deploy_fee_contract(recipient: ContractAddress) -> IERC20CamelDispatcher {
  103. let mut args = array![];
  104. let name: core::byte_array::ByteArray = "eth";
  105. let symbol: core::byte_array::ByteArray = "eth";
  106. (name, symbol, 100000_u256, recipient).serialize(ref args);
  107. let contract = declare("ERC20");
  108. let contract_address = match contract.deploy(@args) {
  109. Result::Ok(v) => { v },
  110. Result::Err(err) => {
  111. panic(err.panic_data);
  112. 0.try_into().unwrap()
  113. },
  114. };
  115. IERC20CamelDispatcher { contract_address }
  116. }
  117. // A random update pulled from Hermes.
  118. fn good_update1() -> ByteArray {
  119. let bytes = array![
  120. 141887862745809943100717722154781668316147089807066324001213790862261653767,
  121. 451230040559159019530944948086670994623010697390864133264612902902585665886,
  122. 355897384610106978643111834734000274494997301794613218547634257521495150151,
  123. 140511063638834349363702006999356227863549404051701803148734324248522745879,
  124. 435849190784772134907557391544163070978531038970298390345939133663347953446,
  125. 416390591179833928094641114955594939466104495718036761707729297119441316151,
  126. 360454929416220920336539568461651500076647166763464050800345920693176904002,
  127. 316054999864337699543932294956493808847640383114707243342262764542081441331,
  128. 325277902980160684959962429721294603784343718796390808940252812862355246813,
  129. 43683235854839458868457367619068018785880460427473556950900276498953667,
  130. 448289429405712011882317781416869052550573589492688760675666957663813001522,
  131. 118081463902430977133121147164253483958565039026724621562859841189218059803,
  132. 194064310618695309465615383754562031677972810736048112738513050109934134235,
  133. 133901765334590923121691219814784557892214901646312752962904032795881821509,
  134. 404227501001709279944936006741063968912686453006275462577777397594240621266,
  135. 81649001731335394114026683805238949464016657447685509824621946636993704965,
  136. 32402065226491532148674904435794801976788068837745943243341272676331333141,
  137. 431262841416902409381606630149292665102873776020834630861578112749151562174,
  138. 6164523115980545628843981978797257048781800754033825701059814297149591186,
  139. 408761574582108996678203805090470134287794603493622537384530614829262728153,
  140. 185368533577943244707350150853170361880334596276529206938783888784867529821,
  141. 173578821500714074579643724957224629379984215847383417303110192934676518530,
  142. 90209855380378362490166376523380463998928070428866100240907090599465187835,
  143. 97758466908511588082569287391708453107999243934457382895073183209581711489,
  144. 132725011490528489913736834798247512772139171145730373610858422315799224432,
  145. 117123868005849140967825260063167768530251411611975150066586827543934313288,
  146. 408149062252618928234854115279677715692278734600386004492580987016428761675,
  147. 164529520317122600276020522906605877985809506451193373524142111430138855019,
  148. 444793051809958482843529748761971363435331354795896511243191618771787268378,
  149. 247660009137502548346315865368477795392972486141407800140910365553760622080,
  150. 3281582060272565111592312037403686940429019548922889497694300188,
  151. 93649805131515836129946966966350066506512123780266587069413066350925286142,
  152. 394112423559676785086098106350541172262729583743734966358666094809121292390,
  153. 35403101004688876764673991514113473446030702766599795822870037077688984558,
  154. 99366103604611980443183454746643823071419076016677225828619807954313149423,
  155. 10381657217606191031071521950784155484751645280452344547752823767622424055,
  156. 391045354044274401116419632681482293741435113770205621235865697077178955228,
  157. 311250087759201408758984550959714865999349469611700431708031036894849650573,
  158. 59953730895385399344628932835545900304309851622811198425230584225200786697,
  159. 226866843267230707879834616967256711063296411939069440476882347301771901839,
  160. 95752383404870925303422787,
  161. ];
  162. ByteArrayImpl::new(array_felt252_to_bytes31(bytes), 11)
  163. }