32
32
AccountId ,
33
33
Gas ,
34
34
Promise ,
35
+ PromiseOrValue ,
35
36
} ,
36
37
num_traits:: FromPrimitive ,
37
38
strum:: EnumDiscriminants ,
@@ -256,7 +257,7 @@ impl Pyth {
256
257
/// done in a callback handler, see `process_vaa_callback`.
257
258
#[ payable]
258
259
#[ 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 > {
260
261
// Verify the VAA is coming from a trusted source chain before attempting to verify VAA
261
262
// signatures. Avoids a cross-contract call early.
262
263
{
@@ -285,22 +286,20 @@ impl Pyth {
285
286
}
286
287
287
288
// 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 ( ) )
289
290
. with_static_gas ( Gas ( 30_000_000_000_000 ) )
290
291
. verify_vaa ( vaa. clone ( ) )
291
292
. then (
292
293
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 ) )
294
295
. with_attached_deposit ( env:: attached_deposit ( ) )
295
296
. verify_gov_vaa_callback ( env:: predecessor_account_id ( ) , vaa) ,
296
297
)
297
298
. then (
298
299
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 ) )
300
301
. refund_vaa ( env:: predecessor_account_id ( ) , env:: attached_deposit ( ) ) ,
301
- ) ;
302
-
303
- Ok ( ( ) )
302
+ ) )
304
303
}
305
304
306
305
/// Invoke handler upon successful verification of a VAA action.
@@ -316,7 +315,7 @@ impl Pyth {
316
315
account_id : AccountId ,
317
316
vaa : String ,
318
317
#[ callback_result] _result : Result < u32 , near_sdk:: PromiseError > ,
319
- ) -> Result < ( ) , Error > {
318
+ ) -> Result < PromiseOrValue < ( ) > , Error > {
320
319
use GovernanceAction :: * ;
321
320
322
321
ensure ! ( is_promise_success( ) , VaaVerificationFailed ) ;
@@ -345,9 +344,6 @@ impl Pyth {
345
344
SetFee { base, expo } => self . set_update_fee ( base, expo) ?,
346
345
SetValidPeriod { valid_seconds } => self . set_valid_period ( valid_seconds) ,
347
346
RequestGovernanceDataSourceTransfer { .. } => Err ( InvalidPayload ) ?,
348
- AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
349
- self . authorize_gov_source_transfer ( claim_vaa) ?
350
- }
351
347
UpgradeContract { codehash } => {
352
348
// Additionally restrict to only Near for upgrades. This is a safety measure to
353
349
// prevent accidental upgrades to the wrong contract.
@@ -357,6 +353,35 @@ impl Pyth {
357
353
) ;
358
354
self . set_upgrade_hash ( codehash)
359
355
}
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
+ }
360
385
}
361
386
362
387
self . executed_governance_vaa = vaa. sequence ;
@@ -368,6 +393,7 @@ impl Pyth {
368
393
env:: storage_usage ( ) ,
369
394
env:: attached_deposit ( ) ,
370
395
)
396
+ . map ( |v| PromiseOrValue :: Value ( v) )
371
397
}
372
398
373
399
/// If submitting an action fails then this callback will refund the caller.
@@ -381,10 +407,18 @@ impl Pyth {
381
407
}
382
408
383
409
#[ private]
410
+ #[ payable]
384
411
#[ 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 ) ?;
386
420
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" ) ;
388
422
389
423
// Convert to local VAA type to catch API changes.
390
424
let vaa = Vaa :: from ( vaa) ;
@@ -410,7 +444,9 @@ impl Pyth {
410
444
InvalidPayload
411
445
) ;
412
446
447
+ // Update executed VAA indices, prevents replay on both the VAA.
413
448
self . executed_governance_change_vaa = governance_data_source_index as u64 ;
449
+ self . executed_governance_vaa = vaa. sequence ;
414
450
415
451
// Update Governance Source
416
452
self . gov_source = Source {
@@ -422,35 +458,13 @@ impl Pyth {
422
458
_ => Err ( Unknown ) ?,
423
459
}
424
460
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
+ )
454
468
}
455
469
456
470
/// This method allows self-upgrading the contract to a new implementation.
@@ -501,6 +515,29 @@ impl Pyth {
501
515
. ok_or ( UnknownSource ( source. emitter ) )
502
516
}
503
517
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
+
504
541
pub fn set_upgrade_hash ( & mut self , codehash : [ u8 ; 32 ] ) {
505
542
self . codehash = codehash;
506
543
}
0 commit comments