[solana/cosmwasm/near] Rust tests refactor (#1238)
* Try * Near * revert * Try to add CI * Cleanup * Cleanup * Fmt * cleanup * Fix CI * Cleanup * Cleanup * Cleanup rust toolchains * Pin to tag * Rename to test-utils * Add deps * Checkpoint * Checkpoint * Checkpoint * Fix wormhole stub * Checkpoint * Start debugging * Green * More green * Cleanup * More cleanup * Cleanup * Factor create_dummy_price_feed_message * Format * Cleanup imports * Cleanup * Near cleanup: * Format * Refactor constants * cleanup * More refactor * Cleanup more magic numbers * Remove magic numbers * Cleanup * Format * Remove magic numnber
This commit is contained in:
parent
82cd11cc77
commit
9697fad077
|
@ -10,6 +10,9 @@ edition = "2021"
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
name = "pythnet_sdk"
|
name = "pythnet_sdk"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
test-utils = ["dep:wormhole-sdk", "dep:serde_wormhole"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
borsh = "0.10.3"
|
borsh = "0.10.3"
|
||||||
|
@ -23,6 +26,12 @@ quickcheck = { version = "1", optional = true}
|
||||||
sha3 = "0.10.4"
|
sha3 = "0.10.4"
|
||||||
slow_primes = "0.1.14"
|
slow_primes = "0.1.14"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
|
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", optional = true, tag="v2.23.37"}
|
||||||
|
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", optional = true, tag="v2.23.37"}
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37"}
|
||||||
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
base64 = "0.21.0"
|
base64 = "0.21.0"
|
||||||
|
|
|
@ -5,6 +5,9 @@ pub mod messages;
|
||||||
pub mod wire;
|
pub mod wire;
|
||||||
pub mod wormhole;
|
pub mod wormhole;
|
||||||
|
|
||||||
|
#[cfg(feature = "test-utils")]
|
||||||
|
pub mod test_utils;
|
||||||
|
|
||||||
pub(crate) type Pubkey = [u8; 32];
|
pub(crate) type Pubkey = [u8; 32];
|
||||||
|
|
||||||
/// Official Message Buffer Program Id
|
/// Official Message Buffer Program Id
|
||||||
|
|
|
@ -0,0 +1,166 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
accumulators::{
|
||||||
|
merkle::MerkleTree,
|
||||||
|
Accumulator,
|
||||||
|
},
|
||||||
|
hashers::keccak256_160::Keccak160,
|
||||||
|
messages::{
|
||||||
|
Message,
|
||||||
|
PriceFeedMessage,
|
||||||
|
},
|
||||||
|
wire::{
|
||||||
|
to_vec,
|
||||||
|
v1::{
|
||||||
|
AccumulatorUpdateData,
|
||||||
|
MerklePriceUpdate,
|
||||||
|
Proof,
|
||||||
|
WormholeMerkleRoot,
|
||||||
|
WormholeMessage,
|
||||||
|
WormholePayload,
|
||||||
|
},
|
||||||
|
PrefixedVec,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
byteorder::BigEndian,
|
||||||
|
serde_wormhole::RawMessage,
|
||||||
|
wormhole_sdk::{
|
||||||
|
Address,
|
||||||
|
Chain,
|
||||||
|
Vaa,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct DataSource {
|
||||||
|
pub address: Address,
|
||||||
|
pub chain: Chain,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const DEFAULT_DATA_SOURCE: DataSource = DataSource {
|
||||||
|
address: Address([1u8; 32]),
|
||||||
|
chain: Chain::Solana,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DEFAULT_GOVERNANCE_SOURCE: DataSource = DataSource {
|
||||||
|
address: Address([2u8; 32]),
|
||||||
|
chain: Chain::Ethereum,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const WRONG_SOURCE: DataSource = DataSource {
|
||||||
|
address: Address([3u8; 32]),
|
||||||
|
chain: Chain::Bsc,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SECONDARY_DATA_SOURCE: DataSource = DataSource {
|
||||||
|
address: Address([4u8; 32]),
|
||||||
|
chain: Chain::Polygon,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SECONDARY_GOVERNANCE_SOURCE: DataSource = DataSource {
|
||||||
|
address: Address([5u8; 32]),
|
||||||
|
chain: Chain::Avalanche,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DEFAULT_CHAIN_ID: Chain = Chain::Oasis;
|
||||||
|
pub const WRONG_CHAIN_ID: Chain = Chain::Algorand;
|
||||||
|
pub const DEFAULT_VALID_TIME_PERIOD: u64 = 180;
|
||||||
|
|
||||||
|
const DEFAULT_SEQUENCE: u64 = 2;
|
||||||
|
|
||||||
|
|
||||||
|
pub fn create_dummy_price_feed_message(value: i64) -> Message {
|
||||||
|
let mut dummy_id = [0; 32];
|
||||||
|
dummy_id[0] = value as u8;
|
||||||
|
let msg = PriceFeedMessage {
|
||||||
|
feed_id: dummy_id,
|
||||||
|
price: value,
|
||||||
|
conf: value as u64,
|
||||||
|
exponent: value as i32,
|
||||||
|
publish_time: value,
|
||||||
|
prev_publish_time: value,
|
||||||
|
ema_price: value,
|
||||||
|
ema_conf: value as u64,
|
||||||
|
};
|
||||||
|
Message::PriceFeedMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_accumulator_message(
|
||||||
|
all_feeds: &[Message],
|
||||||
|
updates: &[Message],
|
||||||
|
corrupt_wormhole_message: bool,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let all_feeds_bytes: Vec<_> = all_feeds
|
||||||
|
.iter()
|
||||||
|
.map(|f| to_vec::<_, BigEndian>(f).unwrap())
|
||||||
|
.collect();
|
||||||
|
let all_feeds_bytes_refs: Vec<_> = all_feeds_bytes.iter().map(|f| f.as_ref()).collect();
|
||||||
|
let tree = MerkleTree::<Keccak160>::new(all_feeds_bytes_refs.as_slice()).unwrap();
|
||||||
|
let mut price_updates: Vec<MerklePriceUpdate> = vec![];
|
||||||
|
for update in updates {
|
||||||
|
let proof = tree
|
||||||
|
.prove(&to_vec::<_, BigEndian>(update).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
price_updates.push(MerklePriceUpdate {
|
||||||
|
message: PrefixedVec::from(to_vec::<_, BigEndian>(update).unwrap()),
|
||||||
|
proof,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
create_accumulator_message_from_updates(
|
||||||
|
price_updates,
|
||||||
|
tree,
|
||||||
|
corrupt_wormhole_message,
|
||||||
|
DEFAULT_DATA_SOURCE.address,
|
||||||
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_accumulator_message_from_updates(
|
||||||
|
price_updates: Vec<MerklePriceUpdate>,
|
||||||
|
tree: MerkleTree<Keccak160>,
|
||||||
|
corrupt_wormhole_message: bool,
|
||||||
|
emitter_address: Address,
|
||||||
|
emitter_chain: Chain,
|
||||||
|
) -> Vec<u8> {
|
||||||
|
let mut root_hash = [0u8; 20];
|
||||||
|
root_hash.copy_from_slice(&to_vec::<_, BigEndian>(&tree.root).unwrap()[..20]);
|
||||||
|
let wormhole_message = WormholeMessage::new(WormholePayload::Merkle(WormholeMerkleRoot {
|
||||||
|
slot: 0,
|
||||||
|
ring_size: 0,
|
||||||
|
root: root_hash,
|
||||||
|
}));
|
||||||
|
|
||||||
|
let mut vaa_payload = to_vec::<_, BigEndian>(&wormhole_message).unwrap();
|
||||||
|
if corrupt_wormhole_message {
|
||||||
|
vaa_payload[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let vaa = create_vaa_from_payload(
|
||||||
|
&vaa_payload,
|
||||||
|
emitter_address,
|
||||||
|
emitter_chain,
|
||||||
|
DEFAULT_SEQUENCE,
|
||||||
|
);
|
||||||
|
|
||||||
|
let accumulator_update_data = AccumulatorUpdateData::new(Proof::WormholeMerkle {
|
||||||
|
vaa: PrefixedVec::from(serde_wormhole::to_vec(&vaa).unwrap()),
|
||||||
|
updates: price_updates,
|
||||||
|
});
|
||||||
|
|
||||||
|
to_vec::<_, BigEndian>(&accumulator_update_data).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_vaa_from_payload(
|
||||||
|
payload: &[u8],
|
||||||
|
emitter_address: Address,
|
||||||
|
emitter_chain: Chain,
|
||||||
|
sequence: u64,
|
||||||
|
) -> Vaa<Box<RawMessage>> {
|
||||||
|
let vaa: Vaa<Box<RawMessage>> = Vaa {
|
||||||
|
emitter_chain: emitter_chain,
|
||||||
|
emitter_address: emitter_address,
|
||||||
|
sequence,
|
||||||
|
payload: <Box<RawMessage>>::from(payload.to_vec()),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
vaa
|
||||||
|
}
|
|
@ -213,6 +213,17 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bstr"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.12.0"
|
version = "3.12.0"
|
||||||
|
@ -1483,10 +1494,12 @@ dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
"serde_wormhole",
|
||||||
"sha3 0.9.1",
|
"sha3 0.9.1",
|
||||||
"terraswap",
|
"terraswap",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"wormhole-cosmwasm",
|
"wormhole-cosmwasm",
|
||||||
|
"wormhole-sdk",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1546,9 +1559,11 @@ dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_wormhole",
|
||||||
"sha3 0.10.8",
|
"sha3 0.10.8",
|
||||||
"slow_primes",
|
"slow_primes",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"wormhole-sdk",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1617,6 +1632,12 @@ dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "region"
|
name = "region"
|
||||||
version = "3.0.0"
|
version = "3.0.0"
|
||||||
|
@ -1857,6 +1878,18 @@ dependencies = [
|
||||||
"syn 2.0.15",
|
"syn 2.0.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_wormhole"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.23.37#846c2e9c9dce18a48745e79ba2ee7eaa5acaf1f4"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"itoa",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.9.9"
|
version = "0.9.9"
|
||||||
|
@ -2661,6 +2694,20 @@ dependencies = [
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wormhole-sdk"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/wormhole-foundation/wormhole?tag=v2.23.37#846c2e9c9dce18a48745e79ba2ee7eaa5acaf1f4"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"bstr",
|
||||||
|
"schemars",
|
||||||
|
"serde",
|
||||||
|
"serde_wormhole",
|
||||||
|
"sha3 0.10.8",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zeroize"
|
name = "zeroize"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
|
|
@ -14,3 +14,6 @@ codegen-units = 1
|
||||||
panic = 'abort'
|
panic = 'abort'
|
||||||
incremental = false
|
incremental = false
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37"}
|
||||||
|
|
|
@ -45,3 +45,6 @@ wormhole-cosmwasm = {git = "https://github.com/wormhole-foundation/wormhole", t
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
cosmwasm-vm = { version = "1.0.0", default-features = false }
|
cosmwasm-vm = { version = "1.0.0", default-features = false }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
pythnet-sdk = { path = "../../../../pythnet/pythnet_sdk", features = ["test-utils"] }
|
||||||
|
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37"}
|
||||||
|
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37"}
|
||||||
|
|
|
@ -835,31 +835,44 @@ mod test {
|
||||||
PriceFeedMessage,
|
PriceFeedMessage,
|
||||||
TwapMessage,
|
TwapMessage,
|
||||||
},
|
},
|
||||||
|
test_utils::{
|
||||||
|
create_accumulator_message,
|
||||||
|
create_accumulator_message_from_updates,
|
||||||
|
create_dummy_price_feed_message,
|
||||||
|
create_vaa_from_payload,
|
||||||
|
DEFAULT_CHAIN_ID,
|
||||||
|
DEFAULT_DATA_SOURCE,
|
||||||
|
DEFAULT_GOVERNANCE_SOURCE,
|
||||||
|
DEFAULT_VALID_TIME_PERIOD,
|
||||||
|
SECONDARY_GOVERNANCE_SOURCE,
|
||||||
|
WRONG_CHAIN_ID,
|
||||||
|
WRONG_SOURCE,
|
||||||
|
},
|
||||||
wire::{
|
wire::{
|
||||||
to_vec,
|
to_vec,
|
||||||
v1::{
|
v1::MerklePriceUpdate,
|
||||||
MerklePriceUpdate,
|
|
||||||
WormholeMerkleRoot,
|
|
||||||
},
|
|
||||||
PrefixedVec,
|
PrefixedVec,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
serde_wormhole::RawMessage,
|
||||||
std::time::Duration,
|
std::time::Duration,
|
||||||
|
wormhole_sdk::{
|
||||||
|
Address,
|
||||||
|
Chain,
|
||||||
|
Vaa,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Default valid time period for testing purposes.
|
/// Default valid time period for testing purposes.
|
||||||
const VALID_TIME_PERIOD: Duration = Duration::from_secs(3 * 60);
|
|
||||||
const WORMHOLE_ADDR: &str = "Wormhole";
|
const WORMHOLE_ADDR: &str = "Wormhole";
|
||||||
const EMITTER_CHAIN: u16 = 3;
|
|
||||||
|
|
||||||
fn default_emitter_addr() -> Vec<u8> {
|
|
||||||
vec![0, 1, 80]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_config_info() -> ConfigInfo {
|
fn default_config_info() -> ConfigInfo {
|
||||||
ConfigInfo {
|
ConfigInfo {
|
||||||
wormhole_contract: Addr::unchecked(WORMHOLE_ADDR),
|
wormhole_contract: Addr::unchecked(WORMHOLE_ADDR),
|
||||||
data_sources: create_data_sources(default_emitter_addr(), EMITTER_CHAIN),
|
data_sources: create_data_sources(
|
||||||
|
DEFAULT_DATA_SOURCE.address.0.to_vec(),
|
||||||
|
DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
),
|
||||||
..create_zero_config_info()
|
..create_zero_config_info()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -871,25 +884,22 @@ mod test {
|
||||||
let mut config = config(dependencies.as_mut().storage);
|
let mut config = config(dependencies.as_mut().storage);
|
||||||
config
|
config
|
||||||
.save(&ConfigInfo {
|
.save(&ConfigInfo {
|
||||||
valid_time_period: VALID_TIME_PERIOD,
|
valid_time_period: Duration::from_secs(DEFAULT_VALID_TIME_PERIOD),
|
||||||
..create_zero_config_info()
|
..create_zero_config_info()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
(dependencies, mock_env())
|
(dependencies, mock_env())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mock handler for wormhole queries.
|
|
||||||
/// Warning: the interface for the `VerifyVAA` action is slightly different than the real wormhole contract.
|
|
||||||
/// In the mock, you pass in a binary-encoded `ParsedVAA`, and that exact vaa will be returned by wormhole.
|
|
||||||
/// The real contract uses a different binary VAA format (see `ParsedVAA::deserialize`) which includes
|
|
||||||
/// the guardian signatures.
|
|
||||||
fn handle_wasm_query(wasm_query: &WasmQuery) -> QuerierResult {
|
fn handle_wasm_query(wasm_query: &WasmQuery) -> QuerierResult {
|
||||||
match wasm_query {
|
match wasm_query {
|
||||||
WasmQuery::Smart { contract_addr, msg } if *contract_addr == WORMHOLE_ADDR => {
|
WasmQuery::Smart { contract_addr, msg } if *contract_addr == WORMHOLE_ADDR => {
|
||||||
let query_msg = from_binary::<WormholeQueryMsg>(msg);
|
let query_msg = from_binary::<WormholeQueryMsg>(msg);
|
||||||
match query_msg {
|
match query_msg {
|
||||||
Ok(WormholeQueryMsg::VerifyVAA { vaa, .. }) => {
|
Ok(WormholeQueryMsg::VerifyVAA { vaa, .. }) => {
|
||||||
SystemResult::Ok(ContractResult::Ok(vaa))
|
SystemResult::Ok(ContractResult::Ok(
|
||||||
|
to_binary(&ParsedVAA::deserialize(&vaa).unwrap()).unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
Err(_e) => SystemResult::Err(SystemError::InvalidRequest {
|
Err(_e) => SystemResult::Err(SystemError::InvalidRequest {
|
||||||
error: "Invalid message".into(),
|
error: "Invalid message".into(),
|
||||||
|
@ -919,45 +929,30 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_zero_vaa() -> ParsedVAA {
|
|
||||||
ParsedVAA {
|
|
||||||
version: 0,
|
|
||||||
guardian_set_index: 0,
|
|
||||||
timestamp: 0,
|
|
||||||
nonce: 0,
|
|
||||||
len_signers: 0,
|
|
||||||
emitter_chain: 0,
|
|
||||||
emitter_address: vec![],
|
|
||||||
sequence: 0,
|
|
||||||
consistency_level: 0,
|
|
||||||
payload: vec![],
|
|
||||||
hash: vec![],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_batch_price_update_msg(
|
fn create_batch_price_update_msg(
|
||||||
emitter_address: &[u8],
|
emitter_address: Address,
|
||||||
emitter_chain: u16,
|
emitter_chain: Chain,
|
||||||
attestations: Vec<PriceAttestation>,
|
attestations: Vec<PriceAttestation>,
|
||||||
) -> Binary {
|
) -> Binary {
|
||||||
let batch_attestation = BatchPriceAttestation {
|
let batch_attestation = BatchPriceAttestation {
|
||||||
price_attestations: attestations,
|
price_attestations: attestations,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut vaa = create_zero_vaa();
|
let vaa = create_vaa_from_payload(
|
||||||
vaa.emitter_address = emitter_address.to_vec();
|
&batch_attestation.serialize().unwrap(),
|
||||||
vaa.emitter_chain = emitter_chain;
|
emitter_address,
|
||||||
vaa.payload = batch_attestation.serialize().unwrap();
|
emitter_chain,
|
||||||
|
0,
|
||||||
to_binary(&vaa).unwrap()
|
);
|
||||||
|
serde_wormhole::to_vec(&vaa).unwrap().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_batch_price_update_msg_from_attestations(
|
fn create_batch_price_update_msg_from_attestations(
|
||||||
attestations: Vec<PriceAttestation>,
|
attestations: Vec<PriceAttestation>,
|
||||||
) -> Binary {
|
) -> Binary {
|
||||||
create_batch_price_update_msg(
|
create_batch_price_update_msg(
|
||||||
default_emitter_addr().as_slice(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
attestations,
|
attestations,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1012,8 +1007,8 @@ mod test {
|
||||||
|
|
||||||
fn apply_price_update(
|
fn apply_price_update(
|
||||||
config_info: &ConfigInfo,
|
config_info: &ConfigInfo,
|
||||||
emitter_address: &[u8],
|
emitter_address: Address,
|
||||||
emitter_chain: u16,
|
emitter_chain: Chain,
|
||||||
attestations: Vec<PriceAttestation>,
|
attestations: Vec<PriceAttestation>,
|
||||||
) -> StdResult<(usize, Vec<PriceFeed>)> {
|
) -> StdResult<(usize, Vec<PriceFeed>)> {
|
||||||
let (mut deps, env) = setup_test();
|
let (mut deps, env) = setup_test();
|
||||||
|
@ -1160,20 +1155,16 @@ mod test {
|
||||||
let feed1 = create_dummy_price_feed_message(100);
|
let feed1 = create_dummy_price_feed_message(100);
|
||||||
let feed2 = create_dummy_price_feed_message(200);
|
let feed2 = create_dummy_price_feed_message(200);
|
||||||
let feed3 = create_dummy_price_feed_message(300);
|
let feed3 = create_dummy_price_feed_message(300);
|
||||||
let data = [create_accumulator_message(
|
let data = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false);
|
||||||
&[feed1, feed2, feed3],
|
check_sufficient_fee(&deps.as_ref(), &[data.into()])
|
||||||
&[feed1],
|
|
||||||
false,
|
|
||||||
)];
|
|
||||||
check_sufficient_fee(&deps.as_ref(), &data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_batch_attestation_empty_array() {
|
fn test_parse_batch_attestation_empty_array() {
|
||||||
let (num_attestations, new_attestations) = apply_price_update(
|
let (num_attestations, new_attestations) = apply_price_update(
|
||||||
&default_config_info(),
|
&default_config_info(),
|
||||||
default_emitter_addr().as_slice(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
vec![],
|
vec![],
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1182,85 +1173,6 @@ mod test {
|
||||||
assert_eq!(new_attestations.len(), 0);
|
assert_eq!(new_attestations.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_dummy_price_feed_message(value: i64) -> Message {
|
|
||||||
let mut dummy_id = [0; 32];
|
|
||||||
dummy_id[0] = value as u8;
|
|
||||||
let msg = PriceFeedMessage {
|
|
||||||
feed_id: dummy_id,
|
|
||||||
price: value,
|
|
||||||
conf: value as u64,
|
|
||||||
exponent: value as i32,
|
|
||||||
publish_time: value,
|
|
||||||
prev_publish_time: value,
|
|
||||||
ema_price: value,
|
|
||||||
ema_conf: value as u64,
|
|
||||||
};
|
|
||||||
Message::PriceFeedMessage(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_accumulator_message_from_updates(
|
|
||||||
price_updates: Vec<MerklePriceUpdate>,
|
|
||||||
tree: MerkleTree<Keccak160>,
|
|
||||||
corrupt_wormhole_message: bool,
|
|
||||||
emitter_address: Vec<u8>,
|
|
||||||
emitter_chain: u16,
|
|
||||||
) -> Binary {
|
|
||||||
let mut root_hash = [0u8; 20];
|
|
||||||
root_hash.copy_from_slice(&to_vec::<_, BigEndian>(&tree.root).unwrap()[..20]);
|
|
||||||
let wormhole_message = WormholeMessage::new(WormholePayload::Merkle(WormholeMerkleRoot {
|
|
||||||
slot: 0,
|
|
||||||
ring_size: 0,
|
|
||||||
root: root_hash,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mut vaa = create_zero_vaa();
|
|
||||||
vaa.emitter_address = emitter_address;
|
|
||||||
vaa.emitter_chain = emitter_chain;
|
|
||||||
vaa.payload = to_vec::<_, BigEndian>(&wormhole_message).unwrap();
|
|
||||||
if corrupt_wormhole_message {
|
|
||||||
vaa.payload[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let vaa_binary = to_binary(&vaa).unwrap();
|
|
||||||
let accumulator_update_data = AccumulatorUpdateData::new(Proof::WormholeMerkle {
|
|
||||||
vaa: PrefixedVec::from(vaa_binary.to_vec()),
|
|
||||||
updates: price_updates,
|
|
||||||
});
|
|
||||||
|
|
||||||
Binary::from(to_vec::<_, BigEndian>(&accumulator_update_data).unwrap())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_accumulator_message(
|
|
||||||
all_feeds: &[Message],
|
|
||||||
updates: &[Message],
|
|
||||||
corrupt_wormhole_message: bool,
|
|
||||||
) -> Binary {
|
|
||||||
let all_feeds_bytes: Vec<_> = all_feeds
|
|
||||||
.iter()
|
|
||||||
.map(|f| to_vec::<_, BigEndian>(f).unwrap())
|
|
||||||
.collect();
|
|
||||||
let all_feeds_bytes_refs: Vec<_> = all_feeds_bytes.iter().map(|f| f.as_ref()).collect();
|
|
||||||
let tree = MerkleTree::<Keccak160>::new(all_feeds_bytes_refs.as_slice()).unwrap();
|
|
||||||
let mut price_updates: Vec<MerklePriceUpdate> = vec![];
|
|
||||||
for update in updates {
|
|
||||||
let proof = tree
|
|
||||||
.prove(&to_vec::<_, BigEndian>(update).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
price_updates.push(MerklePriceUpdate {
|
|
||||||
message: PrefixedVec::from(to_vec::<_, BigEndian>(update).unwrap()),
|
|
||||||
proof,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
create_accumulator_message_from_updates(
|
|
||||||
price_updates,
|
|
||||||
tree,
|
|
||||||
corrupt_wormhole_message,
|
|
||||||
default_emitter_addr(),
|
|
||||||
EMITTER_CHAIN,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn check_price_match(deps: &OwnedDeps<MockStorage, MockApi, MockQuerier>, msg: &Message) {
|
fn check_price_match(deps: &OwnedDeps<MockStorage, MockApi, MockQuerier>, msg: &Message) {
|
||||||
match msg {
|
match msg {
|
||||||
Message::PriceFeedMessage(feed_msg) => {
|
Message::PriceFeedMessage(feed_msg) => {
|
||||||
|
@ -1283,7 +1195,7 @@ mod test {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_accumulator_wrong_source(emitter_address: Vec<u8>, emitter_chain: u16) {
|
fn test_accumulator_wrong_source(emitter_address: Address, emitter_chain: Chain) {
|
||||||
let (mut deps, env) = setup_test();
|
let (mut deps, env) = setup_test();
|
||||||
config(&mut deps.storage)
|
config(&mut deps.storage)
|
||||||
.save(&default_config_info())
|
.save(&default_config_info())
|
||||||
|
@ -1306,20 +1218,19 @@ mod test {
|
||||||
emitter_chain,
|
emitter_chain,
|
||||||
);
|
);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_accumulator_verify_vaa_sender_fail_wrong_emitter_address() {
|
fn test_accumulator_verify_vaa_sender_fail_wrong_emitter_address() {
|
||||||
let emitter_address = [17, 23, 14];
|
test_accumulator_wrong_source(WRONG_SOURCE.address, DEFAULT_DATA_SOURCE.chain);
|
||||||
test_accumulator_wrong_source(emitter_address.to_vec(), EMITTER_CHAIN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_accumulator_verify_vaa_sender_fail_wrong_emitter_chain() {
|
fn test_accumulator_verify_vaa_sender_fail_wrong_emitter_chain() {
|
||||||
test_accumulator_wrong_source(default_emitter_addr(), EMITTER_CHAIN + 1);
|
test_accumulator_wrong_source(DEFAULT_DATA_SOURCE.address, WRONG_SOURCE.chain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1336,23 +1247,32 @@ mod test {
|
||||||
let feed3 = create_dummy_price_feed_message(300);
|
let feed3 = create_dummy_price_feed_message(300);
|
||||||
|
|
||||||
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false);
|
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed3], false);
|
||||||
assert_eq!(get_update_fee_amount(&deps.as_ref(), &[msg]).unwrap(), 200);
|
assert_eq!(
|
||||||
|
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
|
||||||
|
200
|
||||||
|
);
|
||||||
|
|
||||||
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false);
|
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1], false);
|
||||||
assert_eq!(get_update_fee_amount(&deps.as_ref(), &[msg]).unwrap(), 100);
|
assert_eq!(
|
||||||
|
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
|
||||||
|
100
|
||||||
|
);
|
||||||
|
|
||||||
let msg = create_accumulator_message(
|
let msg = create_accumulator_message(
|
||||||
&[feed1, feed2, feed3],
|
&[feed1, feed2, feed3],
|
||||||
&[feed1, feed2, feed3, feed1, feed3],
|
&[feed1, feed2, feed3, feed1, feed3],
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
assert_eq!(get_update_fee_amount(&deps.as_ref(), &[msg]).unwrap(), 500);
|
assert_eq!(
|
||||||
|
get_update_fee_amount(&deps.as_ref(), &[msg.into()]).unwrap(),
|
||||||
|
500
|
||||||
|
);
|
||||||
|
|
||||||
let batch_msg =
|
let batch_msg =
|
||||||
create_batch_price_update_msg_from_attestations(vec![PriceAttestation::default()]);
|
create_batch_price_update_msg_from_attestations(vec![PriceAttestation::default()]);
|
||||||
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
get_update_fee_amount(&deps.as_ref(), &[msg, batch_msg]).unwrap(),
|
get_update_fee_amount(&deps.as_ref(), &[msg.into(), batch_msg]).unwrap(),
|
||||||
400
|
400
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1289,7 @@ mod test {
|
||||||
let feed2 = create_dummy_price_feed_message(200);
|
let feed2 = create_dummy_price_feed_message(200);
|
||||||
let msg = create_accumulator_message(&[feed1, feed2], &[feed1], false);
|
let msg = create_accumulator_message(&[feed1, feed2], &[feed1], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
check_price_match(&deps, &feed1);
|
check_price_match(&deps, &feed1);
|
||||||
}
|
}
|
||||||
|
@ -1386,7 +1306,7 @@ mod test {
|
||||||
}
|
}
|
||||||
let msg = create_accumulator_message(&all_feeds, &all_feeds[100..110], false);
|
let msg = create_accumulator_message(&all_feeds, &all_feeds[100..110], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
for i in 100..110 {
|
for i in 100..110 {
|
||||||
check_price_match(&deps, &all_feeds[i]);
|
check_price_match(&deps, &all_feeds[i]);
|
||||||
|
@ -1421,7 +1341,7 @@ mod test {
|
||||||
let msg2 =
|
let msg2 =
|
||||||
create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg, msg2]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into(), msg2.into()]);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
check_price_match(&deps, &feed1);
|
check_price_match(&deps, &feed1);
|
||||||
|
@ -1442,7 +1362,7 @@ mod test {
|
||||||
as_mut_price_feed(&mut feed2).price *= 2;
|
as_mut_price_feed(&mut feed2).price *= 2;
|
||||||
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
let msg = create_accumulator_message(&[feed1, feed2, feed3], &[feed1, feed2, feed3], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
check_price_match(&deps, &feed1);
|
check_price_match(&deps, &feed1);
|
||||||
|
@ -1464,7 +1384,7 @@ mod test {
|
||||||
|
|
||||||
let msg2 = create_accumulator_message(&[feed1, feed2, feed3], &[feed2, feed3], false);
|
let msg2 = create_accumulator_message(&[feed1, feed2, feed3], &[feed2, feed3], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg, msg2]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into(), msg2.into()]);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
check_price_match(&deps, &feed1);
|
check_price_match(&deps, &feed1);
|
||||||
|
@ -1480,9 +1400,9 @@ mod test {
|
||||||
|
|
||||||
let feed1 = create_dummy_price_feed_message(100);
|
let feed1 = create_dummy_price_feed_message(100);
|
||||||
let mut msg = create_accumulator_message(&[feed1], &[feed1], false);
|
let mut msg = create_accumulator_message(&[feed1], &[feed1], false);
|
||||||
msg.0[4] = 3; // major version
|
msg[4] = 3; // major version
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
|
@ -1500,7 +1420,7 @@ mod test {
|
||||||
let feed1 = create_dummy_price_feed_message(100);
|
let feed1 = create_dummy_price_feed_message(100);
|
||||||
let msg = create_accumulator_message(&[feed1], &[feed1], true);
|
let msg = create_accumulator_message(&[feed1], &[feed1], true);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
|
@ -1528,7 +1448,7 @@ mod test {
|
||||||
});
|
});
|
||||||
let msg = create_accumulator_message(&[feed1], &[feed1], false);
|
let msg = create_accumulator_message(&[feed1], &[feed1], false);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
|
@ -1560,11 +1480,11 @@ mod test {
|
||||||
price_updates,
|
price_updates,
|
||||||
tree,
|
tree,
|
||||||
false,
|
false,
|
||||||
default_emitter_addr(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
);
|
);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
|
@ -1594,11 +1514,11 @@ mod test {
|
||||||
price_updates,
|
price_updates,
|
||||||
tree,
|
tree,
|
||||||
false,
|
false,
|
||||||
default_emitter_addr(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
);
|
);
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
let result = update_price_feeds(deps.as_mut(), env, info, &[msg]);
|
let result = update_price_feeds(deps.as_mut(), env, info, &[msg.into()]);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
result.unwrap_err(),
|
result.unwrap_err(),
|
||||||
|
@ -1779,8 +1699,8 @@ mod test {
|
||||||
fn test_verify_vaa_sender_ok() {
|
fn test_verify_vaa_sender_ok() {
|
||||||
let result = apply_price_update(
|
let result = apply_price_update(
|
||||||
&default_config_info(),
|
&default_config_info(),
|
||||||
default_emitter_addr().as_slice(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
vec![PriceAttestation::default()],
|
vec![PriceAttestation::default()],
|
||||||
);
|
);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
@ -1788,11 +1708,10 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_vaa_sender_fail_wrong_emitter_address() {
|
fn test_verify_vaa_sender_fail_wrong_emitter_address() {
|
||||||
let emitter_address = [17, 23, 14];
|
|
||||||
let result = apply_price_update(
|
let result = apply_price_update(
|
||||||
&default_config_info(),
|
&default_config_info(),
|
||||||
emitter_address.as_slice(),
|
WRONG_SOURCE.address,
|
||||||
EMITTER_CHAIN,
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
vec![PriceAttestation::default()],
|
vec![PriceAttestation::default()],
|
||||||
);
|
);
|
||||||
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
||||||
|
@ -1802,8 +1721,8 @@ mod test {
|
||||||
fn test_verify_vaa_sender_fail_wrong_emitter_chain() {
|
fn test_verify_vaa_sender_fail_wrong_emitter_chain() {
|
||||||
let result = apply_price_update(
|
let result = apply_price_update(
|
||||||
&default_config_info(),
|
&default_config_info(),
|
||||||
default_emitter_addr().as_slice(),
|
DEFAULT_DATA_SOURCE.address,
|
||||||
EMITTER_CHAIN + 1,
|
WRONG_SOURCE.chain,
|
||||||
vec![PriceAttestation::default()],
|
vec![PriceAttestation::default()],
|
||||||
);
|
);
|
||||||
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
assert_eq!(result, Err(PythContractError::InvalidUpdateEmitter.into()));
|
||||||
|
@ -2091,14 +2010,19 @@ mod test {
|
||||||
/// against it. Returns the response of the governance instruction along with the resulting config.
|
/// against it. Returns the response of the governance instruction along with the resulting config.
|
||||||
fn apply_governance_vaa(
|
fn apply_governance_vaa(
|
||||||
initial_config: &ConfigInfo,
|
initial_config: &ConfigInfo,
|
||||||
vaa: &ParsedVAA,
|
vaa: &Vaa<Box<RawMessage>>,
|
||||||
) -> StdResult<(Response<MsgWrapper>, ConfigInfo)> {
|
) -> StdResult<(Response<MsgWrapper>, ConfigInfo)> {
|
||||||
let (mut deps, env) = setup_test();
|
let (mut deps, env) = setup_test();
|
||||||
config(&mut deps.storage).save(initial_config).unwrap();
|
config(&mut deps.storage).save(initial_config).unwrap();
|
||||||
|
|
||||||
let info = mock_info("123", &[]);
|
let info = mock_info("123", &[]);
|
||||||
|
|
||||||
let result = execute_governance_instruction(deps.as_mut(), env, info, &to_binary(&vaa)?);
|
let result = execute_governance_instruction(
|
||||||
|
deps.as_mut(),
|
||||||
|
env,
|
||||||
|
info,
|
||||||
|
&serde_wormhole::to_vec(vaa).unwrap().into(),
|
||||||
|
);
|
||||||
|
|
||||||
result.and_then(|response| config_read(&deps.storage).load().map(|c| (response, c)))
|
result.and_then(|response| config_read(&deps.storage).load().map(|c| (response, c)))
|
||||||
}
|
}
|
||||||
|
@ -2107,23 +2031,22 @@ mod test {
|
||||||
ConfigInfo {
|
ConfigInfo {
|
||||||
wormhole_contract: Addr::unchecked(WORMHOLE_ADDR),
|
wormhole_contract: Addr::unchecked(WORMHOLE_ADDR),
|
||||||
governance_source: PythDataSource {
|
governance_source: PythDataSource {
|
||||||
emitter: Binary(vec![1u8, 2u8]),
|
emitter: Binary(DEFAULT_GOVERNANCE_SOURCE.address.0.to_vec()),
|
||||||
chain_id: 3,
|
chain_id: DEFAULT_GOVERNANCE_SOURCE.chain.into(),
|
||||||
},
|
},
|
||||||
governance_sequence_number: 4,
|
governance_sequence_number: 4,
|
||||||
chain_id: 5,
|
chain_id: DEFAULT_CHAIN_ID.into(),
|
||||||
..create_zero_config_info()
|
..create_zero_config_info()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn governance_vaa(instruction: &GovernanceInstruction) -> ParsedVAA {
|
fn governance_vaa(instruction: &GovernanceInstruction) -> Vaa<Box<RawMessage>> {
|
||||||
let mut vaa = create_zero_vaa();
|
create_vaa_from_payload(
|
||||||
vaa.emitter_address = vec![1u8, 2u8];
|
&instruction.serialize().unwrap(),
|
||||||
vaa.emitter_chain = 3;
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
vaa.sequence = 7;
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
vaa.payload = instruction.serialize().unwrap();
|
7,
|
||||||
|
)
|
||||||
vaa
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -2132,7 +2055,7 @@ mod test {
|
||||||
|
|
||||||
let test_instruction = GovernanceInstruction {
|
let test_instruction = GovernanceInstruction {
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: 5,
|
target_chain_id: DEFAULT_CHAIN_ID.into(),
|
||||||
action: SetFee { val: 6, expo: 0 },
|
action: SetFee { val: 6, expo: 0 },
|
||||||
};
|
};
|
||||||
let test_vaa = governance_vaa(&test_instruction);
|
let test_vaa = governance_vaa(&test_instruction);
|
||||||
|
@ -2142,12 +2065,12 @@ mod test {
|
||||||
|
|
||||||
// Wrong emitter address
|
// Wrong emitter address
|
||||||
let mut vaa_copy = test_vaa.clone();
|
let mut vaa_copy = test_vaa.clone();
|
||||||
vaa_copy.emitter_address = vec![2u8, 3u8];
|
vaa_copy.emitter_address = WRONG_SOURCE.address;
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
|
|
||||||
// wrong source chain
|
// wrong source chain
|
||||||
let mut vaa_copy = test_vaa.clone();
|
let mut vaa_copy = test_vaa.clone();
|
||||||
vaa_copy.emitter_chain = 4;
|
vaa_copy.emitter_chain = WRONG_SOURCE.chain;
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
|
|
||||||
// sequence number too low
|
// sequence number too low
|
||||||
|
@ -2157,53 +2080,50 @@ mod test {
|
||||||
|
|
||||||
// wrong magic number
|
// wrong magic number
|
||||||
let mut vaa_copy = test_vaa.clone();
|
let mut vaa_copy = test_vaa.clone();
|
||||||
vaa_copy.payload[0] = 0;
|
let mut new_payload = vaa_copy.payload.to_vec();
|
||||||
|
new_payload[0] = 0;
|
||||||
|
vaa_copy.payload = <Box<RawMessage>>::from(new_payload);
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
|
|
||||||
// wrong target chain
|
// wrong target chain
|
||||||
let mut instruction_copy = test_instruction.clone();
|
let mut instruction_copy = test_instruction.clone();
|
||||||
instruction_copy.target_chain_id = 6;
|
instruction_copy.target_chain_id = WRONG_CHAIN_ID.into();
|
||||||
let mut vaa_copy = test_vaa.clone();
|
let mut vaa_copy = test_vaa.clone();
|
||||||
vaa_copy.payload = instruction_copy.serialize().unwrap();
|
vaa_copy.payload = <Box<RawMessage>>::from(instruction_copy.serialize().unwrap());
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
|
|
||||||
// target chain == 0 is allowed
|
// target chain == 0 is allowed
|
||||||
let mut instruction_copy = test_instruction.clone();
|
let mut instruction_copy = test_instruction.clone();
|
||||||
instruction_copy.target_chain_id = 0;
|
instruction_copy.target_chain_id = 0;
|
||||||
let mut vaa_copy = test_vaa.clone();
|
let mut vaa_copy = test_vaa.clone();
|
||||||
vaa_copy.payload = instruction_copy.serialize().unwrap();
|
vaa_copy.payload = <Box<RawMessage>>::from(instruction_copy.serialize().unwrap());
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_ok());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_ok());
|
||||||
|
|
||||||
// wrong module
|
// wrong module
|
||||||
let mut instruction_copy = test_instruction.clone();
|
let mut instruction_copy = test_instruction;
|
||||||
instruction_copy.module = Executor;
|
instruction_copy.module = Executor;
|
||||||
let mut vaa_copy = test_vaa;
|
let mut vaa_copy = test_vaa;
|
||||||
vaa_copy.payload = instruction_copy.serialize().unwrap();
|
vaa_copy.payload = <Box<RawMessage>>::from(instruction_copy.serialize().unwrap());
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
|
|
||||||
// invalid action index
|
// invalid action index
|
||||||
let _instruction_copy = test_instruction;
|
let mut new_payload = vaa_copy.payload.to_vec();
|
||||||
vaa_copy.payload[9] = 100;
|
new_payload[9] = 100;
|
||||||
|
vaa_copy.payload = <Box<RawMessage>>::from(new_payload);
|
||||||
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
assert!(apply_governance_vaa(&test_config, &vaa_copy).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_authorize_governance_transfer_success() {
|
fn test_authorize_governance_transfer_success() {
|
||||||
let source_2 = PythDataSource {
|
let source_2 = PythDataSource {
|
||||||
emitter: Binary::from([2u8; 32]),
|
emitter: Binary::from(SECONDARY_GOVERNANCE_SOURCE.address.0),
|
||||||
chain_id: 4,
|
chain_id: SECONDARY_GOVERNANCE_SOURCE.chain.into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let test_config = governance_test_config();
|
let test_config = governance_test_config();
|
||||||
let test_instruction = GovernanceInstruction {
|
|
||||||
module: Target,
|
let claim_vaa = create_vaa_from_payload(
|
||||||
target_chain_id: test_config.chain_id,
|
&GovernanceInstruction {
|
||||||
action: AuthorizeGovernanceDataSourceTransfer {
|
|
||||||
claim_vaa: to_binary(&ParsedVAA {
|
|
||||||
emitter_address: source_2.emitter.to_vec(),
|
|
||||||
emitter_chain: source_2.chain_id,
|
|
||||||
sequence: 12,
|
|
||||||
payload: GovernanceInstruction {
|
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: test_config.chain_id,
|
target_chain_id: test_config.chain_id,
|
||||||
action: RequestGovernanceDataSourceTransfer {
|
action: RequestGovernanceDataSourceTransfer {
|
||||||
|
@ -2212,9 +2132,16 @@ mod test {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..create_zero_vaa()
|
SECONDARY_GOVERNANCE_SOURCE.address,
|
||||||
})
|
SECONDARY_GOVERNANCE_SOURCE.chain,
|
||||||
.unwrap(),
|
12,
|
||||||
|
);
|
||||||
|
|
||||||
|
let test_instruction = GovernanceInstruction {
|
||||||
|
module: Target,
|
||||||
|
target_chain_id: test_config.chain_id,
|
||||||
|
action: AuthorizeGovernanceDataSourceTransfer {
|
||||||
|
claim_vaa: serde_wormhole::to_vec(&claim_vaa).unwrap().into(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2227,22 +2154,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_authorize_governance_transfer_bad_source_index() {
|
fn test_authorize_governance_transfer_bad_source_index() {
|
||||||
let source_2 = PythDataSource {
|
|
||||||
emitter: Binary::from([2u8; 32]),
|
|
||||||
chain_id: 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut test_config = governance_test_config();
|
let mut test_config = governance_test_config();
|
||||||
test_config.governance_source_index = 10;
|
test_config.governance_source_index = 10;
|
||||||
let test_instruction = GovernanceInstruction {
|
|
||||||
module: Target,
|
let claim_vaa = create_vaa_from_payload(
|
||||||
target_chain_id: test_config.chain_id,
|
&GovernanceInstruction {
|
||||||
action: AuthorizeGovernanceDataSourceTransfer {
|
|
||||||
claim_vaa: to_binary(&ParsedVAA {
|
|
||||||
emitter_address: source_2.emitter.to_vec(),
|
|
||||||
emitter_chain: source_2.chain_id,
|
|
||||||
sequence: 12,
|
|
||||||
payload: GovernanceInstruction {
|
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: test_config.chain_id,
|
target_chain_id: test_config.chain_id,
|
||||||
action: RequestGovernanceDataSourceTransfer {
|
action: RequestGovernanceDataSourceTransfer {
|
||||||
|
@ -2251,9 +2167,16 @@ mod test {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..create_zero_vaa()
|
SECONDARY_GOVERNANCE_SOURCE.address,
|
||||||
})
|
SECONDARY_GOVERNANCE_SOURCE.chain,
|
||||||
.unwrap(),
|
12,
|
||||||
|
);
|
||||||
|
|
||||||
|
let test_instruction = GovernanceInstruction {
|
||||||
|
module: Target,
|
||||||
|
target_chain_id: test_config.chain_id,
|
||||||
|
action: AuthorizeGovernanceDataSourceTransfer {
|
||||||
|
claim_vaa: serde_wormhole::to_vec(&claim_vaa).unwrap().into(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2266,32 +2189,28 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_authorize_governance_transfer_bad_target_chain() {
|
fn test_authorize_governance_transfer_bad_target_chain() {
|
||||||
let source_2 = PythDataSource {
|
|
||||||
emitter: Binary::from([2u8; 32]),
|
|
||||||
chain_id: 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
let test_config = governance_test_config();
|
let test_config = governance_test_config();
|
||||||
let test_instruction = GovernanceInstruction {
|
|
||||||
|
let claim_vaa = create_vaa_from_payload(
|
||||||
|
&GovernanceInstruction {
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: test_config.chain_id,
|
target_chain_id: WRONG_CHAIN_ID.into(),
|
||||||
action: AuthorizeGovernanceDataSourceTransfer {
|
|
||||||
claim_vaa: to_binary(&ParsedVAA {
|
|
||||||
emitter_address: source_2.emitter.to_vec(),
|
|
||||||
emitter_chain: source_2.chain_id,
|
|
||||||
sequence: 12,
|
|
||||||
payload: GovernanceInstruction {
|
|
||||||
module: Target,
|
|
||||||
target_chain_id: test_config.chain_id + 1,
|
|
||||||
action: RequestGovernanceDataSourceTransfer {
|
action: RequestGovernanceDataSourceTransfer {
|
||||||
governance_data_source_index: 11,
|
governance_data_source_index: 11,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
..create_zero_vaa()
|
SECONDARY_GOVERNANCE_SOURCE.address,
|
||||||
})
|
SECONDARY_GOVERNANCE_SOURCE.chain,
|
||||||
.unwrap(),
|
12,
|
||||||
|
);
|
||||||
|
|
||||||
|
let test_instruction = GovernanceInstruction {
|
||||||
|
module: Target,
|
||||||
|
target_chain_id: test_config.chain_id,
|
||||||
|
action: AuthorizeGovernanceDataSourceTransfer {
|
||||||
|
claim_vaa: serde_wormhole::to_vec(&claim_vaa).unwrap().into(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2354,7 +2273,7 @@ mod test {
|
||||||
|
|
||||||
let test_instruction = GovernanceInstruction {
|
let test_instruction = GovernanceInstruction {
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: 5,
|
target_chain_id: DEFAULT_CHAIN_ID.into(),
|
||||||
action: SetFee { val: 6, expo: 1 },
|
action: SetFee { val: 6, expo: 1 },
|
||||||
};
|
};
|
||||||
let test_vaa = governance_vaa(&test_instruction);
|
let test_vaa = governance_vaa(&test_instruction);
|
||||||
|
@ -2366,7 +2285,7 @@ mod test {
|
||||||
|
|
||||||
let test_instruction = GovernanceInstruction {
|
let test_instruction = GovernanceInstruction {
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: 5,
|
target_chain_id: DEFAULT_CHAIN_ID.into(),
|
||||||
action: SetFee { val: 6, expo: 0 },
|
action: SetFee { val: 6, expo: 0 },
|
||||||
};
|
};
|
||||||
let test_vaa = governance_vaa(&test_instruction);
|
let test_vaa = governance_vaa(&test_instruction);
|
||||||
|
@ -2384,7 +2303,7 @@ mod test {
|
||||||
|
|
||||||
let test_instruction = GovernanceInstruction {
|
let test_instruction = GovernanceInstruction {
|
||||||
module: Target,
|
module: Target,
|
||||||
target_chain_id: 5,
|
target_chain_id: DEFAULT_CHAIN_ID.into(),
|
||||||
action: SetValidPeriod { valid_seconds: 20 },
|
action: SetValidPeriod { valid_seconds: 20 },
|
||||||
};
|
};
|
||||||
let test_vaa = governance_vaa(&test_instruction);
|
let test_vaa = governance_vaa(&test_instruction);
|
||||||
|
|
|
@ -2239,9 +2239,11 @@ dependencies = [
|
||||||
"hex 0.4.3",
|
"hex 0.4.3",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_wormhole",
|
||||||
"sha3",
|
"sha3",
|
||||||
"slow_primes",
|
"slow_primes",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"wormhole-sdk",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -38,6 +38,7 @@ tokio = { version = "1.23.0", features = ["full"] }
|
||||||
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37" }
|
serde_wormhole = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37" }
|
||||||
workspaces = { version = "0.7.0" }
|
workspaces = { version = "0.7.0" }
|
||||||
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37" }
|
wormhole-sdk = { git = "https://github.com/wormhole-foundation/wormhole", tag="v2.23.37" }
|
||||||
|
pythnet-sdk = { path = "../../../pythnet/pythnet_sdk", features = ["test-utils"] }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use {
|
use {
|
||||||
byteorder::BigEndian,
|
|
||||||
near_sdk::json_types::U128,
|
near_sdk::json_types::U128,
|
||||||
pyth::{
|
pyth::{
|
||||||
governance::{
|
governance::{
|
||||||
|
@ -20,34 +19,17 @@ use {
|
||||||
PriceAttestation,
|
PriceAttestation,
|
||||||
PriceStatus,
|
PriceStatus,
|
||||||
},
|
},
|
||||||
pythnet_sdk::{
|
pythnet_sdk::test_utils::{
|
||||||
accumulators::{
|
create_accumulator_message,
|
||||||
merkle::MerkleTree,
|
create_dummy_price_feed_message,
|
||||||
Accumulator,
|
create_vaa_from_payload,
|
||||||
},
|
DEFAULT_DATA_SOURCE,
|
||||||
hashers::keccak256_160::Keccak160,
|
DEFAULT_GOVERNANCE_SOURCE,
|
||||||
messages::{
|
DEFAULT_VALID_TIME_PERIOD,
|
||||||
Message,
|
SECONDARY_DATA_SOURCE,
|
||||||
PriceFeedMessage,
|
SECONDARY_GOVERNANCE_SOURCE,
|
||||||
},
|
|
||||||
wire::{
|
|
||||||
to_vec,
|
|
||||||
v1::{
|
|
||||||
AccumulatorUpdateData,
|
|
||||||
MerklePriceUpdate,
|
|
||||||
Proof,
|
|
||||||
WormholeMerkleRoot,
|
|
||||||
WormholeMessage,
|
|
||||||
WormholePayload,
|
|
||||||
},
|
|
||||||
PrefixedVec,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
serde_json::json,
|
serde_json::json,
|
||||||
std::io::{
|
|
||||||
Cursor,
|
|
||||||
Write,
|
|
||||||
},
|
|
||||||
wormhole_sdk::Chain as WormholeChain,
|
wormhole_sdk::Chain as WormholeChain,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,10 +74,16 @@ async fn initialize_chain() -> (
|
||||||
.args_json(&json!({
|
.args_json(&json!({
|
||||||
"wormhole": wormhole.id(),
|
"wormhole": wormhole.id(),
|
||||||
"codehash": codehash,
|
"codehash": codehash,
|
||||||
"initial_source": Source::default(),
|
"initial_source": Source {
|
||||||
"gov_source": Source::default(),
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
|
"gov_source": Source {
|
||||||
|
emitter: DEFAULT_GOVERNANCE_SOURCE.address.0,
|
||||||
|
chain: DEFAULT_GOVERNANCE_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
"update_fee": U128::from(1u128),
|
"update_fee": U128::from(1u128),
|
||||||
"stale_threshold": 32,
|
"stale_threshold": DEFAULT_VALID_TIME_PERIOD,
|
||||||
}))
|
}))
|
||||||
.gas(300_000_000_000_000)
|
.gas(300_000_000_000_000)
|
||||||
.transact_async()
|
.transact_async()
|
||||||
|
@ -112,37 +100,30 @@ async fn test_set_sources() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
sequence: 1,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Any),
|
target: Chain::from(WormholeChain::Any),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
action: GovernanceAction::SetDataSources {
|
action: GovernanceAction::SetDataSources {
|
||||||
data_sources: vec![
|
data_sources: vec![
|
||||||
Source::default(),
|
|
||||||
Source {
|
Source {
|
||||||
emitter: [1; 32],
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
chain: Chain::from(WormholeChain::Solana),
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
|
Source {
|
||||||
|
emitter: SECONDARY_DATA_SOURCE.address.0,
|
||||||
|
chain: SECONDARY_DATA_SOURCE.chain.into(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -164,10 +145,13 @@ async fn test_set_sources() {
|
||||||
serde_json::from_slice::<Vec<Source>>(&contract.view("get_sources").await.unwrap().result)
|
serde_json::from_slice::<Vec<Source>>(&contract.view("get_sources").await.unwrap().result)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
&[
|
&[
|
||||||
Source::default(),
|
|
||||||
Source {
|
Source {
|
||||||
emitter: [1; 32],
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
chain: Chain::from(WormholeChain::Solana),
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
|
Source {
|
||||||
|
emitter: SECONDARY_DATA_SOURCE.address.0,
|
||||||
|
chain: SECONDARY_DATA_SOURCE.chain.into(),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -177,30 +161,9 @@ async fn test_set_sources() {
|
||||||
async fn test_set_governance_source() {
|
async fn test_set_governance_source() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
|
||||||
let vaa = wormhole_sdk::Vaa {
|
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 2,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let request_vaa = wormhole_sdk::Vaa {
|
|
||||||
emitter_chain: wormhole_sdk::Chain::Solana,
|
|
||||||
emitter_address: wormhole_sdk::Address([1; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Data Source Upgrades are submitted with an embedded VAA, generate that one here first
|
// Data Source Upgrades are submitted with an embedded VAA, generate that one here first
|
||||||
// before we embed it.
|
// before we embed it.
|
||||||
let request_vaa = {
|
let request_vaa = create_vaa_from_payload(
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &request_vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -210,27 +173,27 @@ async fn test_set_governance_source() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
SECONDARY_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
SECONDARY_GOVERNANCE_SOURCE.chain,
|
||||||
cur.into_inner()
|
1,
|
||||||
};
|
);
|
||||||
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
let vaa = create_vaa_from_payload(
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
action: GovernanceAction::AuthorizeGovernanceDataSourceTransfer {
|
action: GovernanceAction::AuthorizeGovernanceDataSourceTransfer {
|
||||||
claim_vaa: request_vaa,
|
claim_vaa: serde_wormhole::to_vec(&request_vaa).unwrap(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
2,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -247,37 +210,30 @@ async fn test_set_governance_source() {
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
// An action from the new source should now be accepted.
|
// An action from the new source should now be accepted.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
sequence: 3, // NOTE: Incremented Governance Sequence
|
|
||||||
emitter_chain: wormhole_sdk::Chain::Solana,
|
|
||||||
emitter_address: wormhole_sdk::Address([1; 32]),
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
action: GovernanceAction::SetDataSources {
|
action: GovernanceAction::SetDataSources {
|
||||||
data_sources: vec![
|
data_sources: vec![
|
||||||
Source::default(),
|
|
||||||
Source {
|
Source {
|
||||||
emitter: [2; 32],
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
chain: Chain::from(WormholeChain::Solana),
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
|
Source {
|
||||||
|
emitter: SECONDARY_DATA_SOURCE.address.0,
|
||||||
|
chain: SECONDARY_DATA_SOURCE.chain.into(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
SECONDARY_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
SECONDARY_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
2,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -295,18 +251,7 @@ async fn test_set_governance_source() {
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
// But not from the old source.
|
// But not from the old source.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
sequence: 4, // NOTE: Incremented Governance Sequence
|
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -314,18 +259,24 @@ async fn test_set_governance_source() {
|
||||||
data_sources: vec![
|
data_sources: vec![
|
||||||
Source::default(),
|
Source::default(),
|
||||||
Source {
|
Source {
|
||||||
emitter: [2; 32],
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
chain: Chain::from(WormholeChain::Solana),
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
|
},
|
||||||
|
Source {
|
||||||
|
emitter: SECONDARY_DATA_SOURCE.address.0,
|
||||||
|
chain: SECONDARY_DATA_SOURCE.chain.into(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
4,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -347,27 +298,16 @@ async fn test_set_governance_source() {
|
||||||
async fn test_stale_threshold() {
|
async fn test_stale_threshold() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Submit a Price Attestation to the contract.
|
|
||||||
let vaa = wormhole_sdk::Vaa {
|
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get current UNIX timestamp and subtract a minute from it to place the price attestation in
|
// Get current UNIX timestamp and subtract a minute from it to place the price attestation in
|
||||||
// the past. This should be accepted but untrusted.
|
// the past. This should be accepted but untrusted.
|
||||||
let now = std::time::SystemTime::now()
|
let now = std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
.expect("Failed to get UNIX timestamp")
|
.expect("Failed to get UNIX timestamp")
|
||||||
.as_secs()
|
.as_secs()
|
||||||
- 60;
|
- DEFAULT_VALID_TIME_PERIOD;
|
||||||
|
|
||||||
let vaa = {
|
// Submit a Price Attestation to the contract.
|
||||||
let mut cur = Cursor::new(Vec::new());
|
let vaa = create_vaa_from_payload(
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&BatchPriceAttestation {
|
&BatchPriceAttestation {
|
||||||
price_attestations: vec![PriceAttestation {
|
price_attestations: vec![PriceAttestation {
|
||||||
product_id: Identifier::default(),
|
product_id: Identifier::default(),
|
||||||
|
@ -390,10 +330,11 @@ async fn test_stale_threshold() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_DATA_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
let update_fee = serde_json::from_slice::<U128>(
|
let update_fee = serde_json::from_slice::<U128>(
|
||||||
&contract
|
&contract
|
||||||
|
@ -440,18 +381,7 @@ async fn test_stale_threshold() {
|
||||||
|
|
||||||
// Submit another Price Attestation to the contract with an even older timestamp. Which
|
// Submit another Price Attestation to the contract with an even older timestamp. Which
|
||||||
// should now fail due to the existing newer price.
|
// should now fail due to the existing newer price.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
sequence: 2,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&BatchPriceAttestation {
|
&BatchPriceAttestation {
|
||||||
price_attestations: vec![PriceAttestation {
|
price_attestations: vec![PriceAttestation {
|
||||||
product_id: Identifier::default(),
|
product_id: Identifier::default(),
|
||||||
|
@ -474,10 +404,11 @@ async fn test_stale_threshold() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_DATA_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
2,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
// The update handler should now succeed even if price is old, but simply not update the price.
|
// The update handler should now succeed even if price is old, but simply not update the price.
|
||||||
assert!(contract
|
assert!(contract
|
||||||
|
@ -516,18 +447,7 @@ async fn test_stale_threshold() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Now we extend the staleness threshold with a Governance VAA.
|
// Now we extend the staleness threshold with a Governance VAA.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
sequence: 3,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -535,10 +455,11 @@ async fn test_stale_threshold() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
3,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -586,18 +507,7 @@ async fn test_contract_fees() {
|
||||||
.as_secs();
|
.as_secs();
|
||||||
|
|
||||||
// Set a high fee for the contract needed to submit a price.
|
// Set a high fee for the contract needed to submit a price.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -605,10 +515,11 @@ async fn test_contract_fees() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
// Fetch Update fee before changing it.
|
// Fetch Update fee before changing it.
|
||||||
let update_fee = serde_json::from_slice::<U128>(
|
let update_fee = serde_json::from_slice::<U128>(
|
||||||
|
@ -658,18 +569,7 @@ async fn test_contract_fees() {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Attempt to update the price feed with a now too low deposit.
|
// Attempt to update the price feed with a now too low deposit.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
sequence: 2,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&BatchPriceAttestation {
|
&BatchPriceAttestation {
|
||||||
price_attestations: vec![PriceAttestation {
|
price_attestations: vec![PriceAttestation {
|
||||||
product_id: Identifier::default(),
|
product_id: Identifier::default(),
|
||||||
|
@ -692,10 +592,11 @@ async fn test_contract_fees() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_DATA_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_DATA_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
2,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("update_price_feeds")
|
.call("update_price_feeds")
|
||||||
|
@ -734,18 +635,7 @@ async fn test_same_governance_sequence_fails() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Set a high fee for the contract needed to submit a price.
|
// Set a high fee for the contract needed to submit a price.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -753,10 +643,12 @@ async fn test_same_governance_sequence_fails() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
|
|
||||||
// Attempt our first SetFee.
|
// Attempt our first SetFee.
|
||||||
assert!(contract
|
assert!(contract
|
||||||
|
@ -798,18 +690,7 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Set a high fee for the contract needed to submit a price.
|
// Set a high fee for the contract needed to submit a price.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -817,10 +698,11 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
// Attempt our first SetFee.
|
// Attempt our first SetFee.
|
||||||
assert!(contract
|
assert!(contract
|
||||||
|
@ -839,18 +721,7 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
// Generate another VAA with sequence 3.
|
// Generate another VAA with sequence 3.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 3,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -858,10 +729,11 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
3,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
// This should succeed.
|
// This should succeed.
|
||||||
assert!(contract
|
assert!(contract
|
||||||
|
@ -880,18 +752,7 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
.is_empty());
|
.is_empty());
|
||||||
|
|
||||||
// Generate another VAA with sequence 2.
|
// Generate another VAA with sequence 2.
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 2,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Near),
|
target: Chain::from(WormholeChain::Near),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -899,10 +760,11 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
2,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
// This should fail due to being out of order.
|
// This should fail due to being out of order.
|
||||||
assert!(!contract
|
assert!(!contract
|
||||||
|
@ -926,18 +788,7 @@ async fn test_out_of_order_sequences_fail() {
|
||||||
async fn test_governance_target_fails_if_not_near() {
|
async fn test_governance_target_fails_if_not_near() {
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
payload: (),
|
|
||||||
sequence: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).unwrap();
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Solana),
|
target: Chain::from(WormholeChain::Solana),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
|
@ -945,10 +796,12 @@ async fn test_governance_target_fails_if_not_near() {
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.unwrap();
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
|
|
||||||
// This should fail as the target is Solana, when Near is expected.
|
// This should fail as the target is Solana, when Near is expected.
|
||||||
assert!(!contract
|
assert!(!contract
|
||||||
|
@ -970,119 +823,27 @@ async fn test_governance_target_fails_if_not_near() {
|
||||||
// A test to check accumulator style updates work as intended.
|
// A test to check accumulator style updates work as intended.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_accumulator_updates() {
|
async fn test_accumulator_updates() {
|
||||||
fn create_dummy_price_feed_message(value: i64) -> Message {
|
|
||||||
let mut dummy_id = [0; 32];
|
|
||||||
dummy_id[0] = value as u8;
|
|
||||||
let msg = PriceFeedMessage {
|
|
||||||
feed_id: dummy_id,
|
|
||||||
price: value,
|
|
||||||
conf: value as u64,
|
|
||||||
exponent: value as i32,
|
|
||||||
publish_time: value,
|
|
||||||
prev_publish_time: value,
|
|
||||||
ema_price: value,
|
|
||||||
ema_conf: value as u64,
|
|
||||||
};
|
|
||||||
Message::PriceFeedMessage(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_accumulator_message_from_updates(
|
|
||||||
price_updates: Vec<MerklePriceUpdate>,
|
|
||||||
tree: MerkleTree<Keccak160>,
|
|
||||||
emitter_address: [u8; 32],
|
|
||||||
emitter_chain: u16,
|
|
||||||
) -> Vec<u8> {
|
|
||||||
let mut root_hash = [0u8; 20];
|
|
||||||
root_hash.copy_from_slice(&to_vec::<_, BigEndian>(&tree.root).unwrap()[..20]);
|
|
||||||
let wormhole_message = WormholeMessage::new(WormholePayload::Merkle(WormholeMerkleRoot {
|
|
||||||
slot: 0,
|
|
||||||
ring_size: 0,
|
|
||||||
root: root_hash,
|
|
||||||
}));
|
|
||||||
|
|
||||||
let vaa = wormhole_sdk::Vaa {
|
|
||||||
emitter_chain: emitter_chain.into(),
|
|
||||||
emitter_address: wormhole_sdk::Address(emitter_address),
|
|
||||||
sequence: 2,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(&to_vec::<_, BigEndian>(&wormhole_message).unwrap())
|
|
||||||
.expect("Failed to write Payload");
|
|
||||||
cur.into_inner()
|
|
||||||
};
|
|
||||||
|
|
||||||
let accumulator_update_data = AccumulatorUpdateData::new(Proof::WormholeMerkle {
|
|
||||||
vaa: PrefixedVec::from(vaa),
|
|
||||||
updates: price_updates,
|
|
||||||
});
|
|
||||||
|
|
||||||
to_vec::<_, BigEndian>(&accumulator_update_data).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_accumulator_message(all_feeds: &[Message], updates: &[Message]) -> Vec<u8> {
|
|
||||||
let all_feeds_bytes: Vec<_> = all_feeds
|
|
||||||
.iter()
|
|
||||||
.map(|f| to_vec::<_, BigEndian>(f).unwrap())
|
|
||||||
.collect();
|
|
||||||
let all_feeds_bytes_refs: Vec<_> = all_feeds_bytes.iter().map(|f| f.as_ref()).collect();
|
|
||||||
let tree = MerkleTree::<Keccak160>::new(all_feeds_bytes_refs.as_slice()).unwrap();
|
|
||||||
let mut price_updates: Vec<MerklePriceUpdate> = vec![];
|
|
||||||
for update in updates {
|
|
||||||
let proof = tree
|
|
||||||
.prove(&to_vec::<_, BigEndian>(update).unwrap())
|
|
||||||
.unwrap();
|
|
||||||
price_updates.push(MerklePriceUpdate {
|
|
||||||
message: PrefixedVec::from(to_vec::<_, BigEndian>(update).unwrap()),
|
|
||||||
proof,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
create_accumulator_message_from_updates(
|
|
||||||
price_updates,
|
|
||||||
tree,
|
|
||||||
[1; 32],
|
|
||||||
wormhole_sdk::Chain::Any.into(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
let (_, contract, _) = initialize_chain().await;
|
let (_, contract, _) = initialize_chain().await;
|
||||||
|
|
||||||
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
// Submit a new Source to the contract, this will trigger a cross-contract call to wormhole
|
||||||
let vaa = wormhole_sdk::Vaa {
|
let vaa = create_vaa_from_payload(
|
||||||
emitter_chain: wormhole_sdk::Chain::Any,
|
|
||||||
emitter_address: wormhole_sdk::Address([0; 32]),
|
|
||||||
sequence: 1,
|
|
||||||
payload: (),
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let vaa = {
|
|
||||||
let mut cur = Cursor::new(Vec::new());
|
|
||||||
serde_wormhole::to_writer(&mut cur, &vaa).expect("Failed to serialize VAA");
|
|
||||||
cur.write_all(
|
|
||||||
&GovernanceInstruction {
|
&GovernanceInstruction {
|
||||||
target: Chain::from(WormholeChain::Any),
|
target: Chain::from(WormholeChain::Any),
|
||||||
module: GovernanceModule::Target,
|
module: GovernanceModule::Target,
|
||||||
action: GovernanceAction::SetDataSources {
|
action: GovernanceAction::SetDataSources {
|
||||||
data_sources: vec![
|
data_sources: vec![Source {
|
||||||
Source::default(),
|
emitter: DEFAULT_DATA_SOURCE.address.0,
|
||||||
Source {
|
chain: DEFAULT_DATA_SOURCE.chain.into(),
|
||||||
emitter: [1; 32],
|
}],
|
||||||
chain: Chain::from(WormholeChain::Any),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
.serialize()
|
.serialize()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
DEFAULT_GOVERNANCE_SOURCE.address,
|
||||||
.expect("Failed to write Payload");
|
DEFAULT_GOVERNANCE_SOURCE.chain,
|
||||||
hex::encode(cur.into_inner())
|
1,
|
||||||
};
|
);
|
||||||
|
let vaa = hex::encode(serde_wormhole::to_vec(&vaa).unwrap());
|
||||||
|
|
||||||
assert!(contract
|
assert!(contract
|
||||||
.call("execute_governance_instruction")
|
.call("execute_governance_instruction")
|
||||||
|
@ -1102,7 +863,7 @@ async fn test_accumulator_updates() {
|
||||||
// Create a couple of test feeds.
|
// Create a couple of test feeds.
|
||||||
let feed_1 = create_dummy_price_feed_message(100);
|
let feed_1 = create_dummy_price_feed_message(100);
|
||||||
let feed_2 = create_dummy_price_feed_message(200);
|
let feed_2 = create_dummy_price_feed_message(200);
|
||||||
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1]);
|
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1], false);
|
||||||
let message = hex::encode(message);
|
let message = hex::encode(message);
|
||||||
|
|
||||||
// Call the usual UpdatePriceFeed function.
|
// Call the usual UpdatePriceFeed function.
|
||||||
|
@ -1197,8 +958,8 @@ async fn test_borsh_field_cmopat() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
decoded_price,
|
decoded_price,
|
||||||
PriceTester {
|
PriceTester {
|
||||||
price: i64::MAX.into(),
|
price: i64::MAX,
|
||||||
conf: u64::MAX.into(),
|
conf: u64::MAX,
|
||||||
expo: 100,
|
expo: 100,
|
||||||
bad_field_name: 100,
|
bad_field_name: 100,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue