state.move 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. module pyth::state {
  2. use pyth::price_identifier::PriceIdentifier;
  3. use pyth::contract_upgrade_hash::Hash;
  4. use pyth::data_source::DataSource;
  5. use pyth::price_info::PriceInfo;
  6. use std::table::{Self, Table};
  7. use pyth::set::{Self, Set};
  8. use std::vector;
  9. use pyth::error;
  10. use std::account;
  11. friend pyth::pyth;
  12. friend pyth::governance;
  13. friend pyth::contract_upgrade;
  14. friend pyth::set_governance_data_source;
  15. friend pyth::set_update_fee;
  16. friend pyth::set_stale_price_threshold;
  17. friend pyth::set_data_sources;
  18. #[test_only]
  19. friend pyth::governance_test;
  20. /// The valid data sources an attestation VAA can be emitted from
  21. struct DataSources has key {
  22. sources: Set<DataSource>,
  23. }
  24. /// How long a cached price is considered valid for
  25. struct StalePriceThreshold has key {
  26. threshold_secs: u64,
  27. }
  28. /// The update fee charged per VAA
  29. struct BaseUpdateFee has key {
  30. fee: u64,
  31. }
  32. /// The Pyth contract signer capability
  33. struct SignerCapability has key {
  34. signer_capability: account::SignerCapability,
  35. }
  36. /// Mapping of cached price information
  37. ///
  38. /// WARNING: do not directly read out of this table, instead use
  39. /// the checked `pyth::get_price` method. This ensures that the price
  40. /// is recent enough.
  41. struct LatestPriceInfo has key {
  42. info: Table<PriceIdentifier, PriceInfo>,
  43. }
  44. /// The allowed data source for governance VAAs
  45. struct GovernanceDataSource has key {
  46. source: DataSource,
  47. }
  48. /// The last executed governance VAA sequence number
  49. struct LastExecutedGovernanceSequence has key {
  50. sequence: u64,
  51. }
  52. /// The hash of the code of the authorized contract upgrade
  53. struct ContractUpgradeAuthorized has key {
  54. hash: Hash,
  55. }
  56. // Initialization
  57. public(friend) fun init(
  58. pyth: &signer,
  59. stale_price_threshold: u64,
  60. update_fee: u64,
  61. governance_data_source: DataSource,
  62. data_sources: vector<DataSource>,
  63. signer_capability: account::SignerCapability) {
  64. move_to(pyth, StalePriceThreshold{
  65. threshold_secs: stale_price_threshold,
  66. });
  67. move_to(pyth, BaseUpdateFee{
  68. fee: update_fee,
  69. });
  70. let sources = set::new<DataSource>();
  71. while (!vector::is_empty(&data_sources)) {
  72. set::add(&mut sources, vector::pop_back(&mut data_sources));
  73. };
  74. move_to(pyth, DataSources{
  75. sources,
  76. });
  77. move_to(pyth, GovernanceDataSource{
  78. source: governance_data_source,
  79. });
  80. move_to(pyth, LastExecutedGovernanceSequence{
  81. sequence: 0,
  82. });
  83. move_to(pyth, SignerCapability{
  84. signer_capability: signer_capability,
  85. });
  86. move_to(pyth, LatestPriceInfo{
  87. info: table::new<PriceIdentifier, PriceInfo>(),
  88. });
  89. }
  90. // Accessors
  91. public fun get_stale_price_threshold_secs(): u64 acquires StalePriceThreshold {
  92. borrow_global<StalePriceThreshold>(@pyth).threshold_secs
  93. }
  94. public fun get_base_update_fee(): u64 acquires BaseUpdateFee {
  95. borrow_global<BaseUpdateFee>(@pyth).fee
  96. }
  97. public fun is_valid_data_source(data_source: DataSource): bool acquires DataSources {
  98. set::contains(&borrow_global<DataSources>(@pyth).sources, data_source)
  99. }
  100. public fun is_valid_governance_data_source(source: DataSource): bool acquires GovernanceDataSource {
  101. let governance_data_source = borrow_global<GovernanceDataSource>(@pyth);
  102. governance_data_source.source == source
  103. }
  104. public fun get_last_executed_governance_sequence(): u64 acquires LastExecutedGovernanceSequence {
  105. let last_executed_governance_sequence = borrow_global<LastExecutedGovernanceSequence>(@pyth);
  106. last_executed_governance_sequence.sequence
  107. }
  108. public fun price_info_cached(price_identifier: PriceIdentifier): bool acquires LatestPriceInfo {
  109. let latest_price_info = borrow_global<LatestPriceInfo>(@pyth);
  110. table::contains(&latest_price_info.info, price_identifier)
  111. }
  112. public fun get_latest_price_info(price_identifier: PriceIdentifier): PriceInfo acquires LatestPriceInfo {
  113. assert!(price_info_cached(price_identifier), error::unknown_price_feed());
  114. let latest_price_info = borrow_global<LatestPriceInfo>(@pyth);
  115. *table::borrow(&latest_price_info.info, price_identifier)
  116. }
  117. public fun get_contract_upgrade_authorized_hash(): Hash acquires ContractUpgradeAuthorized {
  118. assert!(exists<ContractUpgradeAuthorized>(@pyth), error::unauthorized_upgrade());
  119. let ContractUpgradeAuthorized { hash } = move_from<ContractUpgradeAuthorized>(@pyth);
  120. hash
  121. }
  122. // Setters
  123. public(friend) fun set_data_sources(new_sources: vector<DataSource>) acquires DataSources {
  124. let sources = &mut borrow_global_mut<DataSources>(@pyth).sources;
  125. set::empty(sources);
  126. while (!vector::is_empty(&new_sources)) {
  127. set::add(sources, vector::pop_back(&mut new_sources));
  128. }
  129. }
  130. public(friend) fun set_latest_price_info(price_identifier: PriceIdentifier, price_info: PriceInfo) acquires LatestPriceInfo {
  131. let latest_price_info = borrow_global_mut<LatestPriceInfo>(@pyth);
  132. table::upsert(&mut latest_price_info.info, price_identifier, price_info)
  133. }
  134. public(friend) fun set_last_executed_governance_sequence(sequence: u64) acquires LastExecutedGovernanceSequence {
  135. let last_executed_governance_sequence = borrow_global_mut<LastExecutedGovernanceSequence>(@pyth);
  136. last_executed_governance_sequence.sequence = sequence
  137. }
  138. public(friend) fun pyth_signer(): signer acquires SignerCapability {
  139. account::create_signer_with_capability(&borrow_global<SignerCapability>(@pyth).signer_capability)
  140. }
  141. public(friend) fun set_contract_upgrade_authorized_hash(hash: Hash) acquires ContractUpgradeAuthorized, SignerCapability {
  142. if (exists<ContractUpgradeAuthorized>(@pyth)) {
  143. let ContractUpgradeAuthorized { hash: _ } = move_from<ContractUpgradeAuthorized>(@pyth);
  144. };
  145. move_to(&pyth_signer(), ContractUpgradeAuthorized { hash });
  146. }
  147. public(friend) fun set_governance_data_source(source: DataSource) acquires GovernanceDataSource {
  148. let valid_governance_data_source = borrow_global_mut<GovernanceDataSource>(@pyth);
  149. valid_governance_data_source.source = source;
  150. }
  151. public(friend) fun set_base_update_fee(fee: u64) acquires BaseUpdateFee {
  152. let update_fee = borrow_global_mut<BaseUpdateFee>(@pyth);
  153. update_fee.fee = fee
  154. }
  155. public(friend) fun set_stale_price_threshold_secs(threshold_secs: u64) acquires StalePriceThreshold {
  156. let stale_price_threshold = borrow_global_mut<StalePriceThreshold>(@pyth);
  157. stale_price_threshold.threshold_secs = threshold_secs
  158. }
  159. }