Skip to content

Commit 214bafa

Browse files
committed
near: internal feedback
1 parent 415ca4f commit 214bafa

File tree

3 files changed

+43
-30
lines changed

3 files changed

+43
-30
lines changed

target_chains/near/receiver/src/governance.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ pub enum GovernanceModule {
6666
}
6767

6868
/// A `GovernanceAction` represents the different actions that can be voted on and executed by the
69-
/// governance system.
69+
/// governance system. Note that this implementation is NEAR specific, for example within the
70+
/// UpgradeContract variant we use a codehash unlike a code_id in Cosmwasm, or a Pubkey in Solana.
7071
///
7172
/// [ref:chain_structure] This type uses a [u8; 32] for contract upgrades which differs from other
7273
/// chains, see the reference for more details.
@@ -269,11 +270,6 @@ impl Pyth {
269270
// Convert to local VAA type to catch API changes.
270271
let vaa = Vaa::from(vaa);
271272

272-
ensure!(
273-
self.executed_governance_vaa < vaa.sequence,
274-
VaaVerificationFailed
275-
);
276-
277273
// Confirm the VAA is coming from a trusted source chain.
278274
ensure!(
279275
self.gov_source
@@ -339,6 +335,16 @@ impl Pyth {
339335
InvalidPayload
340336
);
341337

338+
// Ensure the VAA is ahead in sequence, this check is here instead of during
339+
// `execute_governance_instruction` as otherwise someone would be able to slip
340+
// competing actions into the execution stream before the sequence is updated.
341+
ensure!(
342+
self.executed_governance_vaa < vaa.sequence,
343+
VaaVerificationFailed
344+
);
345+
346+
self.executed_governance_vaa = vaa.sequence;
347+
342348
match GovernanceInstruction::deserialize(rest)?.action {
343349
SetDataSources { data_sources } => self.set_sources(data_sources),
344350
SetFee { base, expo } => self.set_update_fee(base, expo)?,
@@ -360,10 +366,13 @@ impl Pyth {
360366
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
361367
let claim_vaa = hex::encode(claim_vaa);
362368

363-
// Return early, the callback has to perform the rest of the processing.
369+
// Return early, the callback has to perform the rest of the processing. Normally
370+
// VAA processing will complete and the code below this match statement will
371+
// execute. But because the VAA verification is async, we must return here instead
372+
// and the logic below is duplicated within the authorize_gov_source_transfer function.
364373
return Ok(PromiseOrValue::Promise(
365374
ext_wormhole::ext(self.wormhole.clone())
366-
.with_static_gas(Gas(30_000_000_000_000))
375+
.with_static_gas(Gas(10_000_000_000_000))
367376
.verify_vaa(claim_vaa.clone())
368377
.then(
369378
Self::ext(env::current_account_id())
@@ -384,14 +393,13 @@ impl Pyth {
384393
}
385394
}
386395

387-
self.executed_governance_vaa = vaa.sequence;
388-
389396
// Refund storage difference to `account_id` after storage execution.
390-
self.refund_storage_usage(
397+
Self::refund_storage_usage(
391398
account_id,
392399
storage,
393400
env::storage_usage(),
394401
env::attached_deposit(),
402+
None,
395403
)
396404
.map(|v| PromiseOrValue::Value(v))
397405
}
@@ -416,6 +424,9 @@ impl Pyth {
416424
storage: u64,
417425
#[callback_result] _result: Result<u32, near_sdk::PromiseError>,
418426
) -> Result<(), Error> {
427+
// If VAA verification failed we should bail.
428+
ensure!(is_promise_success(), VaaVerificationFailed);
429+
419430
let vaa = hex::decode(claim_vaa).map_err(|_| InvalidPayload)?;
420431
let (vaa, rest): (wormhole::Vaa<()>, _) =
421432
serde_wormhole::from_slice_with_payload(&vaa).expect("Failed to deserialize VAA");
@@ -459,11 +470,12 @@ impl Pyth {
459470
}
460471

461472
// Refund storage difference to `account_id` after storage execution.
462-
self.refund_storage_usage(
473+
Self::refund_storage_usage(
463474
account_id,
464475
storage,
465476
env::storage_usage(),
466477
env::attached_deposit(),
478+
None,
467479
)
468480
}
469481

@@ -503,7 +515,7 @@ impl Pyth {
503515
amount: u128,
504516
storage: u64,
505517
) -> Result<(), Error> {
506-
self.refund_storage_usage(account_id, storage, env::storage_usage(), amount)
518+
Self::refund_storage_usage(account_id, storage, env::storage_usage(), amount, None)
507519
}
508520
}
509521

target_chains/near/receiver/src/lib.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl Pyth {
148148
#[init(ignore_state)]
149149
pub fn migrate() -> Self {
150150
// This currently deserializes and produces the same state, I.E migration is a no-op to the
151-
// current state. We only update the codehash to prevent re-upgrading.
151+
// current state.
152152
//
153153
// In the case where we want to actually migrate to a new state, we can do this by defining
154154
// the old State struct here and then deserializing into that, then migrating into the new
@@ -170,7 +170,10 @@ impl Pyth {
170170
//
171171
// // Construct new Pyth State from old, perform any migrations needed.
172172
// let old: OldPyth = env::state_read().expect("Failed to read state");
173+
//
173174
// Self {
175+
// sources: old.sources,
176+
// gov_source: old.gov_source,
174177
// ...
175178
// }
176179
// }
@@ -264,14 +267,7 @@ impl Pyth {
264267
// forces the caller to add the required fee to the deposit. The protocol defines the fee
265268
// as a u128, but storage is a u64, so we need to check that the fee does not overflow the
266269
// storage cost as well.
267-
let storage = (env::storage_usage() as u128)
268-
.checked_sub(
269-
self.update_fee
270-
.checked_div(env::storage_byte_cost())
271-
.ok_or(Error::ArithmeticOverflow)?,
272-
)
273-
.ok_or(Error::InsufficientDeposit)
274-
.and_then(|s| u64::try_from(s).map_err(|_| Error::ArithmeticOverflow))?;
270+
let storage = env::storage_usage();
275271

276272
// Deserialize VAA, note that we already deserialized and verified the VAA in `process_vaa`
277273
// at this point so we only care about the `rest` component which contains bytes we can
@@ -318,11 +314,12 @@ impl Pyth {
318314
);
319315

320316
// Refund storage difference to `account_id` after storage execution.
321-
self.refund_storage_usage(
317+
Self::refund_storage_usage(
322318
account_id,
323319
storage,
324320
env::storage_usage(),
325321
env::attached_deposit(),
322+
Some(self.update_fee),
326323
)
327324
}
328325

@@ -408,11 +405,12 @@ impl Pyth {
408405
);
409406

410407
// Refund storage difference to `account_id` after storage execution.
411-
self.refund_storage_usage(
408+
Self::refund_storage_usage(
412409
account_id,
413410
storage,
414411
env::storage_usage(),
415412
env::attached_deposit(),
413+
Some(self.update_fee),
416414
)
417415
}
418416

@@ -586,18 +584,22 @@ impl Pyth {
586584
}
587585
}
588586

589-
/// Checks storage usage invariants and additionally refunds the caller if they overpay.
587+
/// Checks storage usage invariants and additionally refunds the caller if they overpay. This
588+
/// method can optionally charge a fee to the caller which is removed from their deposit during
589+
/// refund.
590590
fn refund_storage_usage(
591-
&self,
592591
recipient: AccountId,
593592
before: StorageUsage,
594593
after: StorageUsage,
595594
deposit: Balance,
595+
additional_fee: Option<Balance>,
596596
) -> Result<(), Error> {
597+
let fee = additional_fee.unwrap_or(0);
598+
597599
if let Some(diff) = after.checked_sub(before) {
598600
// Handle storage increases if checked_sub succeeds.
599601
let cost = Balance::from(diff);
600-
let cost = cost * env::storage_byte_cost();
602+
let cost = (cost * env::storage_byte_cost()) + fee;
601603

602604
// If the cost is higher than the deposit we bail.
603605
if cost > deposit {
@@ -613,7 +615,7 @@ impl Pyth {
613615
// the amount reduced, as well the original deposit they sent.
614616
let refund = Balance::from(before - after);
615617
let refund = refund * env::storage_byte_cost();
616-
let refund = refund + deposit;
618+
let refund = refund + deposit - fee;
617619
Promise::new(recipient).transfer(refund);
618620
}
619621

target_chains/near/receiver/tests/workspaces.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,9 @@ async fn test_set_governance_source() {
239239
.args_json(&json!({
240240
"vaa": vaa,
241241
}))
242-
.transact_async()
242+
.transact()
243243
.await
244244
.expect("Failed to submit VAA")
245-
.await
246245
.unwrap()
247246
.failures()
248247
.is_empty());

0 commit comments

Comments
 (0)