Skip to content

Commit 8518f90

Browse files
authored
Merge pull request #2889 from pyth-network/pyth-stylus-splitting-lib
refactor(stylus): dividing governance instructions out of lib.rs
2 parents 5f2ab17 + fe686ba commit 8518f90

File tree

2 files changed

+321
-298
lines changed

2 files changed

+321
-298
lines changed
Lines changed: 318 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
use alloc::vec::Vec;
2+
use stylus_sdk::{
3+
alloy_primitives::{Address, FixedBytes, U16, U256, U32, U64},
4+
call::Call,
5+
prelude::*,
6+
};
7+
8+
use crate::{
9+
error::PythReceiverError,
10+
governance_structs::{self, *},
11+
structs::DataSource,
12+
IWormholeContract, PythReceiver,
13+
};
14+
use wormhole_vaas::{Readable, Vaa, Writeable};
15+
16+
impl PythReceiver {
17+
pub fn execute_governance_instruction_internal(
18+
&mut self,
19+
data: Vec<u8>,
20+
) -> Result<(), PythReceiverError> {
21+
let wormhole: IWormholeContract = IWormholeContract::new(self.wormhole.get());
22+
let config = Call::new();
23+
24+
wormhole
25+
.parse_and_verify_vm(config, Vec::from(data.clone()))
26+
.map_err(|_| PythReceiverError::InvalidWormholeMessage)?;
27+
28+
let vm = Vaa::read(&mut Vec::from(data.clone()).as_slice())
29+
.map_err(|_| PythReceiverError::InvalidVaa)?;
30+
31+
verify_governance_vm(self, vm.clone())?;
32+
33+
let instruction = governance_structs::parse_instruction(vm.body.payload.to_vec())
34+
.map_err(|_| PythReceiverError::InvalidGovernanceMessage)?;
35+
36+
let chain_id_config = Call::new();
37+
38+
let wormhole_id = wormhole
39+
.chain_id(chain_id_config)
40+
.map_err(|_| PythReceiverError::WormholeUninitialized)?;
41+
42+
if instruction.target_chain_id != 0 && instruction.target_chain_id != wormhole_id {
43+
return Err(PythReceiverError::InvalidGovernanceTarget);
44+
}
45+
46+
match instruction.payload {
47+
GovernancePayload::SetFee(payload) => {
48+
self.set_fee(payload.value, payload.expo);
49+
}
50+
GovernancePayload::SetDataSources(payload) => {
51+
set_data_sources(self, payload.sources);
52+
}
53+
GovernancePayload::SetWormholeAddress(payload) => {
54+
self.set_wormhole_address(payload.address, data.clone())?;
55+
}
56+
GovernancePayload::RequestGovernanceDataSourceTransfer(_) => {
57+
return Err(PythReceiverError::InvalidGovernanceMessage);
58+
}
59+
GovernancePayload::AuthorizeGovernanceDataSourceTransfer(payload) => {
60+
self.authorize_governance_transfer(payload.claim_vaa)?;
61+
}
62+
GovernancePayload::UpgradeContract(_payload) => {}
63+
GovernancePayload::SetValidPeriod(payload) => {
64+
self.set_valid_period(payload.valid_time_period_seconds);
65+
}
66+
GovernancePayload::SetTransactionFee(payload) => {
67+
self.set_transaction_fee(payload.value, payload.expo);
68+
}
69+
GovernancePayload::WithdrawFee(payload) => {
70+
self.withdraw_fee(payload.value, payload.expo, payload.target_address)?;
71+
}
72+
}
73+
74+
Ok(())
75+
}
76+
77+
fn upgrade_contract(&self, _new_implementation: FixedBytes<32>) {
78+
unimplemented!("Upgrade contract not yet implemented");
79+
}
80+
81+
fn set_fee(&mut self, value: u64, expo: u64) {
82+
let new_fee = U256::from(value).saturating_mul(U256::from(10).pow(U256::from(expo)));
83+
let old_fee = self.single_update_fee_in_wei.get();
84+
85+
self.single_update_fee_in_wei.set(new_fee);
86+
87+
log(self.vm(), crate::FeeSet { old_fee, new_fee });
88+
}
89+
90+
fn set_valid_period(&mut self, valid_time_period_seconds: u64) {
91+
let old_valid_period = self.valid_time_period_seconds.get();
92+
let new_valid_period = U256::from(valid_time_period_seconds);
93+
self.valid_time_period_seconds.set(new_valid_period);
94+
95+
log(
96+
self.vm(),
97+
crate::ValidPeriodSet {
98+
old_valid_period,
99+
new_valid_period,
100+
},
101+
);
102+
}
103+
104+
fn set_wormhole_address(
105+
&mut self,
106+
address: Address,
107+
data: Vec<u8>,
108+
) -> Result<(), PythReceiverError> {
109+
let wormhole: IWormholeContract = IWormholeContract::new(address);
110+
let config = Call::new();
111+
112+
wormhole
113+
.parse_and_verify_vm(config, data.clone())
114+
.map_err(|_| PythReceiverError::InvalidVaa)?;
115+
116+
let vm = Vaa::read(&mut data.as_slice())
117+
.map_err(|_| PythReceiverError::VaaVerificationFailed)?;
118+
119+
if vm.body.emitter_chain != self.governance_data_source_chain_id.get().to::<u16>() {
120+
return Err(PythReceiverError::InvalidGovernanceMessage);
121+
}
122+
123+
if vm.body.emitter_address.as_slice()
124+
!= self.governance_data_source_emitter_address.get().as_slice()
125+
{
126+
return Err(PythReceiverError::InvalidGovernanceMessage);
127+
}
128+
129+
if vm.body.sequence.to::<u64>() <= self.last_executed_governance_sequence.get().to::<u64>()
130+
{
131+
return Err(PythReceiverError::InvalidWormholeAddressToSet);
132+
}
133+
134+
let data = governance_structs::parse_instruction(vm.body.payload.to_vec())
135+
.map_err(|_| PythReceiverError::InvalidGovernanceMessage)?;
136+
137+
match data.payload {
138+
GovernancePayload::SetWormholeAddress(payload) => {
139+
if payload.address != address {
140+
return Err(PythReceiverError::InvalidWormholeAddressToSet);
141+
}
142+
}
143+
_ => return Err(PythReceiverError::InvalidGovernanceMessage),
144+
}
145+
146+
self.wormhole.set(address);
147+
Ok(())
148+
}
149+
150+
fn authorize_governance_transfer(
151+
&mut self,
152+
claim_vaa: Vec<u8>,
153+
) -> Result<(), PythReceiverError> {
154+
let wormhole: IWormholeContract = IWormholeContract::new(self.wormhole.get());
155+
let config = Call::new();
156+
wormhole
157+
.parse_and_verify_vm(config, claim_vaa.clone())
158+
.map_err(|_| PythReceiverError::InvalidWormholeMessage)?;
159+
160+
let claim_vm = Vaa::read(&mut Vec::from(claim_vaa).as_slice())
161+
.map_err(|_| PythReceiverError::VaaVerificationFailed)?;
162+
163+
let instruction = governance_structs::parse_instruction(claim_vm.body.payload.to_vec())
164+
.map_err(|_| PythReceiverError::InvalidGovernanceMessage)?;
165+
166+
let config2 = Call::new();
167+
if instruction.target_chain_id != 0
168+
&& instruction.target_chain_id != wormhole.chain_id(config2).unwrap_or(0)
169+
{
170+
return Err(PythReceiverError::InvalidGovernanceTarget);
171+
}
172+
173+
let request_payload = match instruction.payload {
174+
GovernancePayload::RequestGovernanceDataSourceTransfer(payload) => payload,
175+
_ => return Err(PythReceiverError::InvalidGovernanceMessage),
176+
};
177+
178+
let current_index = self.governance_data_source_index.get().to::<u32>();
179+
let new_index = request_payload.governance_data_source_index;
180+
181+
if current_index >= new_index {
182+
return Err(PythReceiverError::OldGovernanceMessage);
183+
}
184+
185+
self.governance_data_source_index.set(U32::from(new_index));
186+
let old_data_source_emitter_address = self.governance_data_source_emitter_address.get();
187+
188+
self.governance_data_source_chain_id
189+
.set(U16::from(claim_vm.body.emitter_chain));
190+
let emitter_bytes: [u8; 32] = claim_vm
191+
.body
192+
.emitter_address
193+
.as_slice()
194+
.try_into()
195+
.map_err(|_| PythReceiverError::InvalidEmitterAddress)?;
196+
self.governance_data_source_emitter_address
197+
.set(FixedBytes::from(emitter_bytes));
198+
199+
let last_executed_governance_sequence = claim_vm.body.sequence.to::<u64>();
200+
self.last_executed_governance_sequence
201+
.set(U64::from(last_executed_governance_sequence));
202+
203+
log(
204+
self.vm(),
205+
crate::GovernanceDataSourceSet {
206+
old_chain_id: current_index as u16,
207+
old_emitter_address: old_data_source_emitter_address,
208+
new_chain_id: claim_vm.body.emitter_chain,
209+
new_emitter_address: FixedBytes::from(emitter_bytes),
210+
initial_sequence: last_executed_governance_sequence,
211+
},
212+
);
213+
214+
Ok(())
215+
}
216+
217+
fn set_transaction_fee(&mut self, value: u64, expo: u64) {
218+
let new_fee = U256::from(value).saturating_mul(U256::from(10).pow(U256::from(expo)));
219+
let old_fee = self.transaction_fee_in_wei.get();
220+
221+
self.transaction_fee_in_wei.set(new_fee);
222+
223+
log(self.vm(), crate::TransactionFeeSet { old_fee, new_fee });
224+
}
225+
226+
fn withdraw_fee(
227+
&mut self,
228+
value: u64,
229+
expo: u64,
230+
target_address: Address,
231+
) -> Result<(), PythReceiverError> {
232+
let fee_to_withdraw =
233+
U256::from(value).saturating_mul(U256::from(10).pow(U256::from(expo)));
234+
let current_balance = self.vm().balance(self.vm().contract_address());
235+
236+
if current_balance < fee_to_withdraw {
237+
return Err(PythReceiverError::InsufficientFee);
238+
}
239+
240+
self.vm()
241+
.transfer_eth(target_address, fee_to_withdraw)
242+
.map_err(|_| PythReceiverError::InsufficientFee)?;
243+
244+
log(
245+
self.vm(),
246+
crate::FeeWithdrawn {
247+
target_address,
248+
fee_amount: fee_to_withdraw,
249+
},
250+
);
251+
252+
Ok(())
253+
}
254+
}
255+
256+
pub fn verify_governance_vm(receiver: &mut PythReceiver, vm: Vaa) -> Result<(), PythReceiverError> {
257+
if vm.body.emitter_chain != receiver.governance_data_source_chain_id.get().to::<u16>() {
258+
return Err(PythReceiverError::InvalidGovernanceMessage);
259+
}
260+
261+
if vm.body.emitter_address.as_slice()
262+
!= receiver
263+
.governance_data_source_emitter_address
264+
.get()
265+
.as_slice()
266+
{
267+
return Err(PythReceiverError::InvalidGovernanceMessage);
268+
}
269+
270+
let current_sequence = vm.body.sequence.to::<u64>();
271+
let last_executed_sequence = receiver.last_executed_governance_sequence.get().to::<u64>();
272+
273+
if current_sequence <= last_executed_sequence {
274+
return Err(PythReceiverError::GovernanceMessageAlreadyExecuted);
275+
}
276+
277+
receiver
278+
.last_executed_governance_sequence
279+
.set(U64::from(current_sequence));
280+
281+
Ok(())
282+
}
283+
284+
pub fn set_data_sources(receiver: &mut PythReceiver, data_sources: Vec<DataSource>) {
285+
let mut old_data_sources = Vec::new();
286+
for i in 0..receiver.valid_data_sources.len() {
287+
if let Some(storage_data_source) = receiver.valid_data_sources.get(i) {
288+
let data_source = DataSource {
289+
chain_id: storage_data_source.chain_id.get(),
290+
emitter_address: storage_data_source.emitter_address.get(),
291+
};
292+
old_data_sources.push(data_source.emitter_address);
293+
receiver.is_valid_data_source.setter(data_source).set(false);
294+
}
295+
}
296+
297+
receiver.valid_data_sources.erase();
298+
299+
let mut new_data_sources = Vec::new();
300+
for data_source in data_sources {
301+
let mut storage_data_source = receiver.valid_data_sources.grow();
302+
storage_data_source.chain_id.set(data_source.chain_id);
303+
storage_data_source
304+
.emitter_address
305+
.set(data_source.emitter_address);
306+
307+
new_data_sources.push(data_source.emitter_address);
308+
receiver.is_valid_data_source.setter(data_source).set(true);
309+
}
310+
311+
log(
312+
receiver.vm(),
313+
crate::DataSourcesSet {
314+
old_data_sources,
315+
new_data_sources,
316+
},
317+
);
318+
}

0 commit comments

Comments
 (0)