near: internal feedback
This commit is contained in:
parent
415ca4f9b1
commit
214bafa420
|
@ -66,7 +66,8 @@ pub enum GovernanceModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `GovernanceAction` represents the different actions that can be voted on and executed by the
|
/// A `GovernanceAction` represents the different actions that can be voted on and executed by the
|
||||||
/// governance system.
|
/// governance system. Note that this implementation is NEAR specific, for example within the
|
||||||
|
/// UpgradeContract variant we use a codehash unlike a code_id in Cosmwasm, or a Pubkey in Solana.
|
||||||
///
|
///
|
||||||
/// [ref:chain_structure] This type uses a [u8; 32] for contract upgrades which differs from other
|
/// [ref:chain_structure] This type uses a [u8; 32] for contract upgrades which differs from other
|
||||||
/// chains, see the reference for more details.
|
/// chains, see the reference for more details.
|
||||||
|
@ -269,11 +270,6 @@ impl Pyth {
|
||||||
// Convert to local VAA type to catch API changes.
|
// Convert to local VAA type to catch API changes.
|
||||||
let vaa = Vaa::from(vaa);
|
let vaa = Vaa::from(vaa);
|
||||||
|
|
||||||
ensure!(
|
|
||||||
self.executed_governance_vaa < vaa.sequence,
|
|
||||||
VaaVerificationFailed
|
|
||||||
);
|
|
||||||
|
|
||||||
// Confirm the VAA is coming from a trusted source chain.
|
// Confirm the VAA is coming from a trusted source chain.
|
||||||
ensure!(
|
ensure!(
|
||||||
self.gov_source
|
self.gov_source
|
||||||
|
@ -339,6 +335,16 @@ impl Pyth {
|
||||||
InvalidPayload
|
InvalidPayload
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Ensure the VAA is ahead in sequence, this check is here instead of during
|
||||||
|
// `execute_governance_instruction` as otherwise someone would be able to slip
|
||||||
|
// competing actions into the execution stream before the sequence is updated.
|
||||||
|
ensure!(
|
||||||
|
self.executed_governance_vaa < vaa.sequence,
|
||||||
|
VaaVerificationFailed
|
||||||
|
);
|
||||||
|
|
||||||
|
self.executed_governance_vaa = vaa.sequence;
|
||||||
|
|
||||||
match GovernanceInstruction::deserialize(rest)?.action {
|
match GovernanceInstruction::deserialize(rest)?.action {
|
||||||
SetDataSources { data_sources } => self.set_sources(data_sources),
|
SetDataSources { data_sources } => self.set_sources(data_sources),
|
||||||
SetFee { base, expo } => self.set_update_fee(base, expo)?,
|
SetFee { base, expo } => self.set_update_fee(base, expo)?,
|
||||||
|
@ -360,10 +366,13 @@ impl Pyth {
|
||||||
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
|
AuthorizeGovernanceDataSourceTransfer { claim_vaa } => {
|
||||||
let claim_vaa = hex::encode(claim_vaa);
|
let claim_vaa = hex::encode(claim_vaa);
|
||||||
|
|
||||||
// Return early, the callback has to perform the rest of the processing.
|
// Return early, the callback has to perform the rest of the processing. Normally
|
||||||
|
// VAA processing will complete and the code below this match statement will
|
||||||
|
// execute. But because the VAA verification is async, we must return here instead
|
||||||
|
// and the logic below is duplicated within the authorize_gov_source_transfer function.
|
||||||
return Ok(PromiseOrValue::Promise(
|
return Ok(PromiseOrValue::Promise(
|
||||||
ext_wormhole::ext(self.wormhole.clone())
|
ext_wormhole::ext(self.wormhole.clone())
|
||||||
.with_static_gas(Gas(30_000_000_000_000))
|
.with_static_gas(Gas(10_000_000_000_000))
|
||||||
.verify_vaa(claim_vaa.clone())
|
.verify_vaa(claim_vaa.clone())
|
||||||
.then(
|
.then(
|
||||||
Self::ext(env::current_account_id())
|
Self::ext(env::current_account_id())
|
||||||
|
@ -384,14 +393,13 @@ impl Pyth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.executed_governance_vaa = vaa.sequence;
|
|
||||||
|
|
||||||
// Refund storage difference to `account_id` after storage execution.
|
// Refund storage difference to `account_id` after storage execution.
|
||||||
self.refund_storage_usage(
|
Self::refund_storage_usage(
|
||||||
account_id,
|
account_id,
|
||||||
storage,
|
storage,
|
||||||
env::storage_usage(),
|
env::storage_usage(),
|
||||||
env::attached_deposit(),
|
env::attached_deposit(),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
.map(|v| PromiseOrValue::Value(v))
|
.map(|v| PromiseOrValue::Value(v))
|
||||||
}
|
}
|
||||||
|
@ -416,6 +424,9 @@ impl Pyth {
|
||||||
storage: u64,
|
storage: u64,
|
||||||
#[callback_result] _result: Result<u32, near_sdk::PromiseError>,
|
#[callback_result] _result: Result<u32, near_sdk::PromiseError>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
// If VAA verification failed we should bail.
|
||||||
|
ensure!(is_promise_success(), VaaVerificationFailed);
|
||||||
|
|
||||||
let vaa = hex::decode(claim_vaa).map_err(|_| InvalidPayload)?;
|
let vaa = hex::decode(claim_vaa).map_err(|_| InvalidPayload)?;
|
||||||
let (vaa, rest): (wormhole::Vaa<()>, _) =
|
let (vaa, rest): (wormhole::Vaa<()>, _) =
|
||||||
serde_wormhole::from_slice_with_payload(&vaa).expect("Failed to deserialize VAA");
|
serde_wormhole::from_slice_with_payload(&vaa).expect("Failed to deserialize VAA");
|
||||||
|
@ -459,11 +470,12 @@ impl Pyth {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refund storage difference to `account_id` after storage execution.
|
// Refund storage difference to `account_id` after storage execution.
|
||||||
self.refund_storage_usage(
|
Self::refund_storage_usage(
|
||||||
account_id,
|
account_id,
|
||||||
storage,
|
storage,
|
||||||
env::storage_usage(),
|
env::storage_usage(),
|
||||||
env::attached_deposit(),
|
env::attached_deposit(),
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,7 +515,7 @@ impl Pyth {
|
||||||
amount: u128,
|
amount: u128,
|
||||||
storage: u64,
|
storage: u64,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
self.refund_storage_usage(account_id, storage, env::storage_usage(), amount)
|
Self::refund_storage_usage(account_id, storage, env::storage_usage(), amount, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,7 +148,7 @@ impl Pyth {
|
||||||
#[init(ignore_state)]
|
#[init(ignore_state)]
|
||||||
pub fn migrate() -> Self {
|
pub fn migrate() -> Self {
|
||||||
// This currently deserializes and produces the same state, I.E migration is a no-op to the
|
// This currently deserializes and produces the same state, I.E migration is a no-op to the
|
||||||
// current state. We only update the codehash to prevent re-upgrading.
|
// current state.
|
||||||
//
|
//
|
||||||
// In the case where we want to actually migrate to a new state, we can do this by defining
|
// In the case where we want to actually migrate to a new state, we can do this by defining
|
||||||
// the old State struct here and then deserializing into that, then migrating into the new
|
// the old State struct here and then deserializing into that, then migrating into the new
|
||||||
|
@ -170,7 +170,10 @@ impl Pyth {
|
||||||
//
|
//
|
||||||
// // Construct new Pyth State from old, perform any migrations needed.
|
// // Construct new Pyth State from old, perform any migrations needed.
|
||||||
// let old: OldPyth = env::state_read().expect("Failed to read state");
|
// let old: OldPyth = env::state_read().expect("Failed to read state");
|
||||||
|
//
|
||||||
// Self {
|
// Self {
|
||||||
|
// sources: old.sources,
|
||||||
|
// gov_source: old.gov_source,
|
||||||
// ...
|
// ...
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
@ -264,14 +267,7 @@ impl Pyth {
|
||||||
// forces the caller to add the required fee to the deposit. The protocol defines the fee
|
// forces the caller to add the required fee to the deposit. The protocol defines the fee
|
||||||
// as a u128, but storage is a u64, so we need to check that the fee does not overflow the
|
// as a u128, but storage is a u64, so we need to check that the fee does not overflow the
|
||||||
// storage cost as well.
|
// storage cost as well.
|
||||||
let storage = (env::storage_usage() as u128)
|
let storage = env::storage_usage();
|
||||||
.checked_sub(
|
|
||||||
self.update_fee
|
|
||||||
.checked_div(env::storage_byte_cost())
|
|
||||||
.ok_or(Error::ArithmeticOverflow)?,
|
|
||||||
)
|
|
||||||
.ok_or(Error::InsufficientDeposit)
|
|
||||||
.and_then(|s| u64::try_from(s).map_err(|_| Error::ArithmeticOverflow))?;
|
|
||||||
|
|
||||||
// Deserialize VAA, note that we already deserialized and verified the VAA in `process_vaa`
|
// Deserialize VAA, note that we already deserialized and verified the VAA in `process_vaa`
|
||||||
// at this point so we only care about the `rest` component which contains bytes we can
|
// at this point so we only care about the `rest` component which contains bytes we can
|
||||||
|
@ -318,11 +314,12 @@ impl Pyth {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Refund storage difference to `account_id` after storage execution.
|
// Refund storage difference to `account_id` after storage execution.
|
||||||
self.refund_storage_usage(
|
Self::refund_storage_usage(
|
||||||
account_id,
|
account_id,
|
||||||
storage,
|
storage,
|
||||||
env::storage_usage(),
|
env::storage_usage(),
|
||||||
env::attached_deposit(),
|
env::attached_deposit(),
|
||||||
|
Some(self.update_fee),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,11 +405,12 @@ impl Pyth {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Refund storage difference to `account_id` after storage execution.
|
// Refund storage difference to `account_id` after storage execution.
|
||||||
self.refund_storage_usage(
|
Self::refund_storage_usage(
|
||||||
account_id,
|
account_id,
|
||||||
storage,
|
storage,
|
||||||
env::storage_usage(),
|
env::storage_usage(),
|
||||||
env::attached_deposit(),
|
env::attached_deposit(),
|
||||||
|
Some(self.update_fee),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -586,18 +584,22 @@ impl Pyth {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks storage usage invariants and additionally refunds the caller if they overpay.
|
/// Checks storage usage invariants and additionally refunds the caller if they overpay. This
|
||||||
|
/// method can optionally charge a fee to the caller which is removed from their deposit during
|
||||||
|
/// refund.
|
||||||
fn refund_storage_usage(
|
fn refund_storage_usage(
|
||||||
&self,
|
|
||||||
recipient: AccountId,
|
recipient: AccountId,
|
||||||
before: StorageUsage,
|
before: StorageUsage,
|
||||||
after: StorageUsage,
|
after: StorageUsage,
|
||||||
deposit: Balance,
|
deposit: Balance,
|
||||||
|
additional_fee: Option<Balance>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
let fee = additional_fee.unwrap_or(0);
|
||||||
|
|
||||||
if let Some(diff) = after.checked_sub(before) {
|
if let Some(diff) = after.checked_sub(before) {
|
||||||
// Handle storage increases if checked_sub succeeds.
|
// Handle storage increases if checked_sub succeeds.
|
||||||
let cost = Balance::from(diff);
|
let cost = Balance::from(diff);
|
||||||
let cost = cost * env::storage_byte_cost();
|
let cost = (cost * env::storage_byte_cost()) + fee;
|
||||||
|
|
||||||
// If the cost is higher than the deposit we bail.
|
// If the cost is higher than the deposit we bail.
|
||||||
if cost > deposit {
|
if cost > deposit {
|
||||||
|
@ -613,7 +615,7 @@ impl Pyth {
|
||||||
// the amount reduced, as well the original deposit they sent.
|
// the amount reduced, as well the original deposit they sent.
|
||||||
let refund = Balance::from(before - after);
|
let refund = Balance::from(before - after);
|
||||||
let refund = refund * env::storage_byte_cost();
|
let refund = refund * env::storage_byte_cost();
|
||||||
let refund = refund + deposit;
|
let refund = refund + deposit - fee;
|
||||||
Promise::new(recipient).transfer(refund);
|
Promise::new(recipient).transfer(refund);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -239,10 +239,9 @@ async fn test_set_governance_source() {
|
||||||
.args_json(&json!({
|
.args_json(&json!({
|
||||||
"vaa": vaa,
|
"vaa": vaa,
|
||||||
}))
|
}))
|
||||||
.transact_async()
|
.transact()
|
||||||
.await
|
.await
|
||||||
.expect("Failed to submit VAA")
|
.expect("Failed to submit VAA")
|
||||||
.await
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.failures()
|
.failures()
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
Loading…
Reference in New Issue