From e3fe85c3123d571cbe58b8586a492341053a81c5 Mon Sep 17 00:00:00 2001 From: optke3 <108488464+optke3@users.noreply.github.com> Date: Wed, 12 Jul 2023 12:47:45 -0400 Subject: [PATCH] [Sui 18/x] - governance action tests (#949) * on-chain tests for governance actions * edit name * edit * remove governance data source test that is not working * edit comment --- .../sui/contracts/sources/data_source.move | 2 + .../sources/governance/governance_action.move | 1 - .../sources/governance/set_data_sources.move | 56 +++++++++++++++++++ .../governance/set_stale_price_threshold.move | 51 +++++++++++++++++ .../sources/governance/set_update_fee.move | 51 +++++++++++++++++ target_chains/sui/contracts/sources/pyth.move | 12 +++- 6 files changed, 169 insertions(+), 4 deletions(-) diff --git a/target_chains/sui/contracts/sources/data_source.move b/target_chains/sui/contracts/sources/data_source.move index c97e444c..280aebe8 100644 --- a/target_chains/sui/contracts/sources/data_source.move +++ b/target_chains/sui/contracts/sources/data_source.move @@ -13,6 +13,8 @@ module pyth::data_source { friend pyth::set_governance_data_source; #[test_only] friend pyth::pyth_tests; + #[test_only] + friend pyth::set_data_sources_tests; const KEY: vector = b"data_sources"; const E_DATA_SOURCE_REGISTRY_ALREADY_EXISTS: u64 = 0; diff --git a/target_chains/sui/contracts/sources/governance/governance_action.move b/target_chains/sui/contracts/sources/governance/governance_action.move index 4bfcb767..6bfce10a 100644 --- a/target_chains/sui/contracts/sources/governance/governance_action.move +++ b/target_chains/sui/contracts/sources/governance/governance_action.move @@ -1,5 +1,4 @@ module pyth::governance_action { - //use pyth::error; const CONTRACT_UPGRADE: u8 = 0; const SET_GOVERNANCE_DATA_SOURCE: u8 = 1; diff --git a/target_chains/sui/contracts/sources/governance/set_data_sources.move b/target_chains/sui/contracts/sources/governance/set_data_sources.move index f4a840d7..8efab3fd 100644 --- a/target_chains/sui/contracts/sources/governance/set_data_sources.move +++ b/target_chains/sui/contracts/sources/governance/set_data_sources.move @@ -72,3 +72,59 @@ module pyth::set_data_sources { } } } + +#[test_only] +module pyth::set_data_sources_tests { + use sui::test_scenario::{Self}; + use sui::coin::Self; + + use wormhole::governance_message::verify_vaa; + use wormhole::external_address::{Self}; + use wormhole::bytes32::{Self}; + + use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states}; + use pyth::set_data_sources::{Self}; + use pyth::state::Self; + use pyth::data_source::Self; + + const SET_DATA_SOURCES_VAA: vector = x"01000000000100ac52663a7e50ab23db4f00f0607d930ffd438c5a214b3013418b57117590f76c32d2f790ec62be5f6e69d96273b1a567b8a698a8f5069c1ccd27a6874af2adc00100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010200155054474d01020015030001f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6001ae101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71"; + // VAA Info: + // module name: 0x1 + // action: 2 + // chain: 21 + // data sources (chain, addr) pairs: [(1, 0xf346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0), (26, 0xa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6), (26, 0xe101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71)] + + const DEPLOYER: address = @0x1234; + const DEFAULT_BASE_UPDATE_FEE: u64 = 0; + const DEFAULT_COIN_TO_MINT: u64 = 0; + + #[test] + fun set_data_sources(){ + let (scenario, test_coins, clock) = setup_test(500, 1, x"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385", pyth_tests::data_sources_for_test_vaa(), vector[x"13947bd48b18e53fdaeee77f3473391ac727c638"], DEFAULT_BASE_UPDATE_FEE, DEFAULT_COIN_TO_MINT); + test_scenario::next_tx(&mut scenario, DEPLOYER); + let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario); + + let ticket = set_data_sources::authorize_governance(&pyth_state, false); + + let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_DATA_SOURCES_VAA, &clock); + + let receipt = verify_vaa(&worm_state, verified_vaa, ticket); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + pyth::governance::execute_governance_instruction(&mut pyth_state, receipt); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + // assert data sources are set correctly + + assert!(state::is_valid_data_source(&pyth_state, data_source::new(1, external_address::new(bytes32::from_bytes(x"f346195ac02f37d60d4db8ffa6ef74cb1be3550047543a4a9ee9acf4d78697b0")))), 0); + assert!(state::is_valid_data_source(&pyth_state, data_source::new(26, external_address::new(bytes32::from_bytes(x"a27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6")))), 0); + assert!(state::is_valid_data_source(&pyth_state, data_source::new(26, external_address::new(bytes32::from_bytes(x"e101faedac5851e32b9b23b5f9411a8c2bac4aae3ed4dd7b811dd1a72ea4aa71")))), 0); + + // clean up + coin::burn_for_testing(test_coins); + pyth_tests::cleanup_worm_state_pyth_state_and_clock(worm_state, pyth_state, clock); + test_scenario::end(scenario); + } +} diff --git a/target_chains/sui/contracts/sources/governance/set_stale_price_threshold.move b/target_chains/sui/contracts/sources/governance/set_stale_price_threshold.move index 808d9e53..ed5df545 100644 --- a/target_chains/sui/contracts/sources/governance/set_stale_price_threshold.move +++ b/target_chains/sui/contracts/sources/governance/set_stale_price_threshold.move @@ -50,3 +50,54 @@ module pyth::set_stale_price_threshold { } } } + +#[test_only] +module pyth::set_stale_price_threshold_test { + use sui::test_scenario::{Self}; + use sui::coin::Self; + + use wormhole::governance_message::verify_vaa; + + use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states}; + use pyth::set_stale_price_threshold::{Self}; + use pyth::state::Self; + + const SET_STALE_PRICE_THRESHOLD_VAA: vector = x"01000000000100196a91724d472b6c160c44ddcc9f9cef531aa95442739300023048bd066b77ca1a02bbfd9ff1799f3d63a4dd10c5348ab3b231e3bb66232e0cb4c07daa3647090100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010400155054474d0104001500000000000aee23"; + // VAA Info: + // module name: 0x1 + // action: 4 + // chain: 21 + // stale price threshold: 716323 + + const DEPLOYER: address = @0x1234; + const DEFAULT_BASE_UPDATE_FEE: u64 = 0; + const DEFAULT_COIN_TO_MINT: u64 = 0; + + #[test] + fun set_stale_price_threshold(){ + + let (scenario, test_coins, clock) = setup_test(500, 1, x"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385", pyth_tests::data_sources_for_test_vaa(), vector[x"13947bd48b18e53fdaeee77f3473391ac727c638"], DEFAULT_BASE_UPDATE_FEE, DEFAULT_COIN_TO_MINT); + test_scenario::next_tx(&mut scenario, DEPLOYER); + let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario); + + let ticket = set_stale_price_threshold::authorize_governance(&pyth_state, false); + + let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_STALE_PRICE_THRESHOLD_VAA, &clock); + + let receipt = verify_vaa(&worm_state, verified_vaa, ticket); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + pyth::governance::execute_governance_instruction(&mut pyth_state, receipt); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + // assert stale price threshold is set correctly + assert!(state::get_stale_price_threshold_secs(&pyth_state)==716323, 0); + + // clean up + coin::burn_for_testing(test_coins); + pyth_tests::cleanup_worm_state_pyth_state_and_clock(worm_state, pyth_state, clock); + test_scenario::end(scenario); + } +} \ No newline at end of file diff --git a/target_chains/sui/contracts/sources/governance/set_update_fee.move b/target_chains/sui/contracts/sources/governance/set_update_fee.move index 9cdd1f82..e5e4db2b 100644 --- a/target_chains/sui/contracts/sources/governance/set_update_fee.move +++ b/target_chains/sui/contracts/sources/governance/set_update_fee.move @@ -65,3 +65,54 @@ module pyth::set_update_fee { mantissa * math::pow(10, exponent) } } + +#[test_only] +module pyth::set_update_fee_tests { + use sui::test_scenario::{Self}; + use sui::coin::Self; + + use wormhole::governance_message::verify_vaa; + + use pyth::pyth_tests::{Self, setup_test, take_wormhole_and_pyth_states}; + use pyth::set_update_fee::{Self}; + use pyth::state::Self; + + const SET_FEE_VAA: vector = x"01000000000100e773bfd4a262ecd012333a953aadd243b8c116cc059b970ecb91216675eff89a39438570efb6eedcea15dad71d6ad0a18a7d01617e3cf61d53339df705a36df00100bc614e00000000000163278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c38500000000000000010100000000000000000000000000000000000000000000000000000000000000010300155054474d0103001500000000000000030000000000000002"; + // VAA Info: + // module name: 0x1 + // action: 3 + // chain: 21 + // new fee: 3, new exponent: 2 + + const DEPLOYER: address = @0x1234; + const DEFAULT_BASE_UPDATE_FEE: u64 = 0; + const DEFAULT_COIN_TO_MINT: u64 = 0; + + #[test] + fun set_update_fee(){ + + let (scenario, test_coins, clock) = setup_test(500, 1, x"63278d271099bfd491951b3e648f08b1c71631e4a53674ad43e8f9f98068c385", pyth_tests::data_sources_for_test_vaa(), vector[x"13947bd48b18e53fdaeee77f3473391ac727c638"], DEFAULT_BASE_UPDATE_FEE, DEFAULT_COIN_TO_MINT); + test_scenario::next_tx(&mut scenario, DEPLOYER); + let (pyth_state, worm_state) = take_wormhole_and_pyth_states(&scenario); + + let ticket = set_update_fee::authorize_governance(&pyth_state, false); + + let verified_vaa = wormhole::vaa::parse_and_verify(&mut worm_state, SET_FEE_VAA, &clock); + + let receipt = verify_vaa(&worm_state, verified_vaa, ticket); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + pyth::governance::execute_governance_instruction(&mut pyth_state, receipt); + + test_scenario::next_tx(&mut scenario, DEPLOYER); + + // assert fee is set correctly + assert!(state::get_base_update_fee(&pyth_state)==300, 0); + + // clean up + coin::burn_for_testing(test_coins); + pyth_tests::cleanup_worm_state_pyth_state_and_clock(worm_state, pyth_state, clock); + test_scenario::end(scenario); + } +} diff --git a/target_chains/sui/contracts/sources/pyth.move b/target_chains/sui/contracts/sources/pyth.move index a4e6bd89..04e955b1 100644 --- a/target_chains/sui/contracts/sources/pyth.move +++ b/target_chains/sui/contracts/sources/pyth.move @@ -36,6 +36,12 @@ module pyth::pyth { #[test_only] friend pyth::pyth_tests; + #[test_only] + friend pyth::set_data_sources_tests; + #[test_only] + friend pyth::set_stale_price_threshold_test; + #[test_only] + friend pyth::set_update_fee_tests; /// Init state and emit event corresponding to Pyth initialization. public entry fun init_pyth( @@ -742,7 +748,7 @@ module pyth::pyth_tests{ test_scenario::end(scenario); } - fun data_sources_for_test_vaa(): vector { + public fun data_sources_for_test_vaa(): vector { // Set some valid data sources, including our test VAA's source vector[ data_source::new( @@ -1544,13 +1550,13 @@ module pyth::pyth_tests{ ) } - fun cleanup_worm_state_pyth_state_and_clock(worm_state: WormState, pyth_state: PythState, clock: Clock){ + public fun cleanup_worm_state_pyth_state_and_clock(worm_state: WormState, pyth_state: PythState, clock: Clock){ return_shared(worm_state); return_shared(pyth_state); clock::destroy_for_testing(clock); } - fun take_wormhole_and_pyth_states(scenario: &Scenario): (PythState, WormState){ + public fun take_wormhole_and_pyth_states(scenario: &Scenario): (PythState, WormState){ (take_shared(scenario), take_shared(scenario)) } }