Skip to content

Commit 415ca4f

Browse files
committed
near: add vaa verify to claim, also fixes private
1 parent bd24d4d commit 415ca4f

File tree

1 file changed

+79
-42
lines changed

1 file changed

+79
-42
lines changed

target_chains/near/receiver/src/governance.rs

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use {
3232
AccountId,
3333
Gas,
3434
Promise,
35+
PromiseOrValue,
3536
},
3637
num_traits::FromPrimitive,
3738
strum::EnumDiscriminants,
@@ -256,7 +257,7 @@ impl Pyth {
256257
/// done in a callback handler, see `process_vaa_callback`.
257258
#[payable]
258259
#[handle_result]
259-
pub fn execute_governance_instruction(&mut self, vaa: String) -> Result<(), Error> {
260+
pub fn execute_governance_instruction(&mut self, vaa: String) -> Result<Promise, Error> {
260261
// Verify the VAA is coming from a trusted source chain before attempting to verify VAA
261262
// signatures. Avoids a cross-contract call early.
262263
{
@@ -285,22 +286,20 @@ impl Pyth {
285286
}
286287

287288
// Verify VAA and refund the caller in case of failure.
288-
ext_wormhole::ext(self.wormhole.clone())
289+
Ok(ext_wormhole::ext(self.wormhole.clone())
289290
.with_static_gas(Gas(30_000_000_000_000))
290291
.verify_vaa(vaa.clone())
291292
.then(
292293
Self::ext(env::current_account_id())
293-
.with_static_gas(Gas(30_000_000_000_000))
294+
.with_static_gas(Gas(10_000_000_000_000))
294295
.with_attached_deposit(env::attached_deposit())
295296
.verify_gov_vaa_callback(env::predecessor_account_id(), vaa),
296297
)
297298
.then(
298299
Self::ext(env::current_account_id())
299-
.with_static_gas(Gas(30_000_000_000_000))
300+
.with_static_gas(Gas(10_000_000_000_000))
300301
.refund_vaa(env::predecessor_account_id(), env::attached_deposit()),
301-
);
302-
303-
Ok(())
302+
))
304303
}
305304

306305
/// Invoke handler upon successful verification of a VAA action.
@@ -316,7 +315,7 @@ impl Pyth {
316315
account_id: AccountId,
317316
vaa: String,
318317
#[callback_result] _result: Result<u32, near_sdk::PromiseError>,
319-
) -> Result<(), Error> {
318+
) -> Result<PromiseOrValue<()>, Error> {
320319
use GovernanceAction::*;
321320

322321
ensure!(is_promise_success(), VaaVerificationFailed);
@@ -345,9 +344,6 @@ impl Pyth {
345344
SetFee { base, expo } => self.set_update_fee(base, expo)?,
346345
SetValidPeriod { valid_seconds } => self.set_valid_period(valid_seconds),
347346
RequestGovernanceDataSourceTransfer { .. } => Err(InvalidPayload)?,
348-
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
349-
self.authorize_gov_source_transfer(claim_vaa)?
350-
}
351347
UpgradeContract { codehash } => {
352348
// Additionally restrict to only Near for upgrades. This is a safety measure to
353349
// prevent accidental upgrades to the wrong contract.
@@ -357,6 +353,35 @@ impl Pyth {
357353
);
358354
self.set_upgrade_hash(codehash)
359355
}
356+
357+
// In the case of AuthorizeGovernanceDataSourceTransfer we need to verify the VAA
358+
// contained within the action. This implies another async call so we return here and
359+
// allow the refund / gov processing to happen in the callback.
360+
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
361+
let claim_vaa = hex::encode(claim_vaa);
362+
363+
// Return early, the callback has to perform the rest of the processing.
364+
return Ok(PromiseOrValue::Promise(
365+
ext_wormhole::ext(self.wormhole.clone())
366+
.with_static_gas(Gas(30_000_000_000_000))
367+
.verify_vaa(claim_vaa.clone())
368+
.then(
369+
Self::ext(env::current_account_id())
370+
.with_static_gas(Gas(10_000_000_000_000))
371+
.with_attached_deposit(env::attached_deposit())
372+
.authorize_gov_source_transfer(
373+
env::predecessor_account_id(),
374+
claim_vaa,
375+
storage,
376+
),
377+
)
378+
.then(
379+
Self::ext(env::current_account_id())
380+
.with_static_gas(Gas(10_000_000_000_000))
381+
.refund_vaa(env::predecessor_account_id(), env::attached_deposit()),
382+
),
383+
));
384+
}
360385
}
361386

362387
self.executed_governance_vaa = vaa.sequence;
@@ -368,6 +393,7 @@ impl Pyth {
368393
env::storage_usage(),
369394
env::attached_deposit(),
370395
)
396+
.map(|v| PromiseOrValue::Value(v))
371397
}
372398

373399
/// If submitting an action fails then this callback will refund the caller.
@@ -381,10 +407,18 @@ impl Pyth {
381407
}
382408

383409
#[private]
410+
#[payable]
384411
#[handle_result]
385-
pub fn authorize_gov_source_transfer(&mut self, claim_vaa: Vec<u8>) -> Result<(), Error> {
412+
pub fn authorize_gov_source_transfer(
413+
&mut self,
414+
account_id: AccountId,
415+
claim_vaa: String,
416+
storage: u64,
417+
#[callback_result] _result: Result<u32, near_sdk::PromiseError>,
418+
) -> Result<(), Error> {
419+
let vaa = hex::decode(claim_vaa).map_err(|_| InvalidPayload)?;
386420
let (vaa, rest): (wormhole::Vaa<()>, _) =
387-
serde_wormhole::from_slice_with_payload(&claim_vaa).expect("Failed to deserialize VAA");
421+
serde_wormhole::from_slice_with_payload(&vaa).expect("Failed to deserialize VAA");
388422

389423
// Convert to local VAA type to catch API changes.
390424
let vaa = Vaa::from(vaa);
@@ -410,7 +444,9 @@ impl Pyth {
410444
InvalidPayload
411445
);
412446

447+
// Update executed VAA indices, prevents replay on both the VAA.
413448
self.executed_governance_change_vaa = governance_data_source_index as u64;
449+
self.executed_governance_vaa = vaa.sequence;
414450

415451
// Update Governance Source
416452
self.gov_source = Source {
@@ -422,35 +458,13 @@ impl Pyth {
422458
_ => Err(Unknown)?,
423459
}
424460

425-
Ok(())
426-
}
427-
428-
#[private]
429-
pub fn set_valid_period(&mut self, threshold: u64) {
430-
self.stale_threshold = threshold;
431-
}
432-
433-
#[private]
434-
#[handle_result]
435-
pub fn set_update_fee(&mut self, fee: u64, expo: u64) -> Result<(), Error> {
436-
self.update_fee = (fee as u128)
437-
.checked_mul(
438-
10_u128
439-
.checked_pow(u32::try_from(expo).map_err(|_| ArithmeticOverflow)?)
440-
.ok_or(ArithmeticOverflow)?,
441-
)
442-
.ok_or(ArithmeticOverflow)?;
443-
444-
Ok(())
445-
}
446-
447-
#[private]
448-
#[handle_result]
449-
pub fn set_sources(&mut self, sources: Vec<Source>) {
450-
self.sources.clear();
451-
sources.iter().for_each(|s| {
452-
self.sources.insert(s);
453-
});
461+
// Refund storage difference to `account_id` after storage execution.
462+
self.refund_storage_usage(
463+
account_id,
464+
storage,
465+
env::storage_usage(),
466+
env::attached_deposit(),
467+
)
454468
}
455469

456470
/// This method allows self-upgrading the contract to a new implementation.
@@ -501,6 +515,29 @@ impl Pyth {
501515
.ok_or(UnknownSource(source.emitter))
502516
}
503517

518+
pub fn set_valid_period(&mut self, threshold: u64) {
519+
self.stale_threshold = threshold;
520+
}
521+
522+
pub fn set_update_fee(&mut self, fee: u64, expo: u64) -> Result<(), Error> {
523+
self.update_fee = (fee as u128)
524+
.checked_mul(
525+
10_u128
526+
.checked_pow(u32::try_from(expo).map_err(|_| ArithmeticOverflow)?)
527+
.ok_or(ArithmeticOverflow)?,
528+
)
529+
.ok_or(ArithmeticOverflow)?;
530+
531+
Ok(())
532+
}
533+
534+
pub fn set_sources(&mut self, sources: Vec<Source>) {
535+
self.sources.clear();
536+
sources.iter().for_each(|s| {
537+
self.sources.insert(s);
538+
});
539+
}
540+
504541
pub fn set_upgrade_hash(&mut self, codehash: [u8; 32]) {
505542
self.codehash = codehash;
506543
}

0 commit comments

Comments
 (0)