|
@@ -3,7 +3,11 @@ mod interface;
|
|
|
mod price_update;
|
|
mod price_update;
|
|
|
mod governance;
|
|
mod governance;
|
|
|
|
|
|
|
|
-pub use pyth::{Event, PriceFeedUpdateEvent, WormholeAddressSet, GovernanceDataSourceSet};
|
|
|
|
|
|
|
+mod fake_upgrades;
|
|
|
|
|
+
|
|
|
|
|
+pub use pyth::{
|
|
|
|
|
+ Event, PriceFeedUpdateEvent, WormholeAddressSet, GovernanceDataSourceSet, ContractUpgraded
|
|
|
|
|
+};
|
|
|
pub use errors::{GetPriceUnsafeError, GovernanceActionError, UpdatePriceFeedsError};
|
|
pub use errors::{GetPriceUnsafeError, GovernanceActionError, UpdatePriceFeedsError};
|
|
|
pub use interface::{IPyth, IPythDispatcher, IPythDispatcherTrait, DataSource, Price};
|
|
pub use interface::{IPyth, IPythDispatcher, IPythDispatcherTrait, DataSource, Price};
|
|
|
|
|
|
|
@@ -16,10 +20,15 @@ mod pyth {
|
|
|
use pyth::reader::{Reader, ReaderImpl};
|
|
use pyth::reader::{Reader, ReaderImpl};
|
|
|
use pyth::byte_array::{ByteArray, ByteArrayImpl};
|
|
use pyth::byte_array::{ByteArray, ByteArrayImpl};
|
|
|
use core::panic_with_felt252;
|
|
use core::panic_with_felt252;
|
|
|
- use core::starknet::{ContractAddress, get_caller_address, get_execution_info};
|
|
|
|
|
|
|
+ use core::starknet::{
|
|
|
|
|
+ ContractAddress, get_caller_address, get_execution_info, ClassHash, SyscallResultTrait,
|
|
|
|
|
+ get_contract_address,
|
|
|
|
|
+ };
|
|
|
|
|
+ use core::starknet::syscalls::replace_class_syscall;
|
|
|
use pyth::wormhole::{IWormholeDispatcher, IWormholeDispatcherTrait, VerifiedVM};
|
|
use pyth::wormhole::{IWormholeDispatcher, IWormholeDispatcherTrait, VerifiedVM};
|
|
|
use super::{
|
|
use super::{
|
|
|
- DataSource, UpdatePriceFeedsError, GovernanceActionError, Price, GetPriceUnsafeError
|
|
|
|
|
|
|
+ DataSource, UpdatePriceFeedsError, GovernanceActionError, Price, GetPriceUnsafeError,
|
|
|
|
|
+ IPythDispatcher, IPythDispatcherTrait,
|
|
|
};
|
|
};
|
|
|
use super::governance;
|
|
use super::governance;
|
|
|
use super::governance::GovernancePayload;
|
|
use super::governance::GovernancePayload;
|
|
@@ -31,6 +40,7 @@ mod pyth {
|
|
|
PriceFeedUpdate: PriceFeedUpdateEvent,
|
|
PriceFeedUpdate: PriceFeedUpdateEvent,
|
|
|
WormholeAddressSet: WormholeAddressSet,
|
|
WormholeAddressSet: WormholeAddressSet,
|
|
|
GovernanceDataSourceSet: GovernanceDataSourceSet,
|
|
GovernanceDataSourceSet: GovernanceDataSourceSet,
|
|
|
|
|
+ ContractUpgraded: ContractUpgraded,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[derive(Drop, PartialEq, starknet::Event)]
|
|
#[derive(Drop, PartialEq, starknet::Event)]
|
|
@@ -55,6 +65,11 @@ mod pyth {
|
|
|
pub last_executed_governance_sequence: u64,
|
|
pub last_executed_governance_sequence: u64,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ #[derive(Drop, PartialEq, starknet::Event)]
|
|
|
|
|
+ pub struct ContractUpgraded {
|
|
|
|
|
+ pub new_class_hash: ClassHash,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
#[storage]
|
|
#[storage]
|
|
|
struct Storage {
|
|
struct Storage {
|
|
|
wormhole_address: ContractAddress,
|
|
wormhole_address: ContractAddress,
|
|
@@ -243,8 +258,18 @@ mod pyth {
|
|
|
GovernancePayload::AuthorizeGovernanceDataSourceTransfer(payload) => {
|
|
GovernancePayload::AuthorizeGovernanceDataSourceTransfer(payload) => {
|
|
|
self.authorize_governance_transfer(payload.claim_vaa);
|
|
self.authorize_governance_transfer(payload.claim_vaa);
|
|
|
},
|
|
},
|
|
|
|
|
+ GovernancePayload::UpgradeContract(payload) => {
|
|
|
|
|
+ if instruction.target_chain_id == 0 {
|
|
|
|
|
+ panic_with_felt252(GovernanceActionError::InvalidGovernanceTarget.into());
|
|
|
|
|
+ }
|
|
|
|
|
+ self.upgrade_contract(payload.new_implementation);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ fn pyth_upgradable_magic(self: @ContractState) -> u32 {
|
|
|
|
|
+ 0x97a6f304
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#[generate_trait]
|
|
#[generate_trait]
|
|
@@ -385,6 +410,18 @@ mod pyth {
|
|
|
};
|
|
};
|
|
|
self.emit(event);
|
|
self.emit(event);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ fn upgrade_contract(ref self: ContractState, new_implementation: ClassHash) {
|
|
|
|
|
+ let contract_address = get_contract_address();
|
|
|
|
|
+ replace_class_syscall(new_implementation).unwrap_syscall();
|
|
|
|
|
+ // Dispatcher uses `call_contract_syscall` so it will call the new implementation.
|
|
|
|
|
+ let magic = IPythDispatcher { contract_address }.pyth_upgradable_magic();
|
|
|
|
|
+ if magic != 0x97a6f304 {
|
|
|
|
|
+ panic_with_felt252(GovernanceActionError::InvalidGovernanceMessage.into());
|
|
|
|
|
+ }
|
|
|
|
|
+ let event = ContractUpgraded { new_class_hash: new_implementation };
|
|
|
|
|
+ self.emit(event);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
fn apply_decimal_expo(value: u64, expo: u64) -> u256 {
|
|
fn apply_decimal_expo(value: u64, expo: u64) -> u256 {
|