diff --git a/.gitignore b/.gitignore index 6a9604b..7660b0f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -cosmwasm/artifacts -cosmwasm/target -cw-relayer/build \ No newline at end of file +cosmwasm/* +cw-relayer/build + +# ide files +.idea \ No newline at end of file diff --git a/cosmwasm/contracts/price-feed/examples/schema.rs b/cosmwasm/contracts/price-feed/examples/schema.rs index 2ffc644..0bcb05b 100644 --- a/cosmwasm/contracts/price-feed/examples/schema.rs +++ b/cosmwasm/contracts/price-feed/examples/schema.rs @@ -4,7 +4,7 @@ use std::fs::create_dir_all; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; use std_reference::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; -use std_reference::state::{RefData, ReferenceData, RefMedianData}; +use std_reference::state::{RefData, RefMedianData, ReferenceData}; fn main() { let mut out_dir = current_dir().unwrap(); diff --git a/cosmwasm/contracts/price-feed/src/contract.rs b/cosmwasm/contracts/price-feed/src/contract.rs index 165a685..fddd2ae 100644 --- a/cosmwasm/contracts/price-feed/src/contract.rs +++ b/cosmwasm/contracts/price-feed/src/contract.rs @@ -1,6 +1,9 @@ use crate::errors::ContractError; -use crate::msg::{ExecuteMsg, InstantiateMsg,QueryMsg}; -use crate::state::{RefData, RefStore, ReferenceData, WhitelistedRelayers, ADMIN, RELAYERS, RefMedianData, RefMedianStore, MEDIANSTATUS, RefDeviationStore}; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; +use crate::state::{ + RefData, RefDeviationData, RefDeviationStore, RefMedianData, RefMedianStore, RefStore, + ReferenceData, WhitelistedRelayers, ADMIN, MEDIANSTATUS, RELAYERS, +}; use cosmwasm_std::{ entry_point, to_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult, Uint256, Uint64, @@ -21,7 +24,7 @@ pub fn instantiate( let admin = info.sender; ADMIN.save(deps.storage, &admin.clone())?; - MEDIANSTATUS.save(deps.storage,&true)?; + MEDIANSTATUS.save(deps.storage, &true)?; Ok(Response::default()) } @@ -140,9 +143,7 @@ fn execute_relay( // Checks if sender is a relayer let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } // Saves price data @@ -172,9 +173,7 @@ fn execute_relay_historical_median( // Checks if sender is a relayer let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } if !MEDIANSTATUS.load(deps.storage)? { @@ -209,9 +208,7 @@ fn execute_force_relay( let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } for (symbol, rate) in symbol_rates { @@ -235,9 +232,7 @@ fn execute_force_relay_historical_median( let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } for (symbol, rates) in symbol_rates { @@ -254,20 +249,18 @@ fn execute_force_relay_historical_median( fn execute_relay_historical_deviation( deps: DepsMut, info: MessageInfo, - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, request_id: Uint64, ) -> Result { // Checks if sender is a relayer let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } // Saves price data - for (symbol, rate) in symbol_rates { + for (symbol, rates) in symbol_rates { if let Some(existing_refdata) = RefDeviationStore::load(deps.storage, &symbol) { if existing_refdata.resolve_time >= resolve_time { continue; @@ -277,7 +270,7 @@ fn execute_relay_historical_deviation( RefDeviationStore::save( deps.storage, &symbol, - &RefData::new(rate, resolve_time, request_id), + &RefDeviationData::new(rates, resolve_time, request_id), )? } @@ -287,24 +280,22 @@ fn execute_relay_historical_deviation( fn execute_force_relay_historical_deviation( deps: DepsMut, info: MessageInfo, - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, request_id: Uint64, ) -> Result { // Checks if sender is a relayer let sender_addr = &info.sender; if !query_is_relayer(deps.as_ref(), sender_addr)? { - return Err(ContractError::Unauthorized { - msg: String::from("Sender is not a relayer"), - }); + return Err(ContractError::UnauthorizedRelayer {}); } // Saves price data - for (symbol, rate) in symbol_rates { + for (symbol, rates) in symbol_rates { RefDeviationStore::save( deps.storage, &symbol, - &RefData::new(rate, resolve_time, request_id), + &RefDeviationData::new(rates, resolve_time, request_id), )? } @@ -376,9 +367,7 @@ fn query_reference_data_bulk( fn assert_admin(config_admin: &Addr, account: &Addr) -> Result<(), ContractError> { if config_admin != account { - return Err(ContractError::Admin { - msg: String::from("ADMIN ONLY"), - }); + return Err(ContractError::UnauthorizedAdmin {}); } Ok(()) @@ -387,13 +376,13 @@ fn assert_admin(config_admin: &Addr, account: &Addr) -> Result<(), ContractError // can only support USD fn query_median_ref(deps: Deps, symbol: &str) -> StdResult { if !MEDIANSTATUS.load(deps.storage)? { - return Err(StdError::generic_err ("MEDIAN DISABLED")); + return Err(StdError::generic_err("MEDIAN DISABLED")); } if symbol == "USD" { Ok(RefMedianData::new(vec![E9], Uint64::MAX, Uint64::zero())) } else { - let data = RefMedianStore::load(deps.storage, symbol); + let data = RefMedianStore::load(deps.storage, symbol); data.ok_or(StdError::not_found("std_reference::state::RefData")) } } @@ -405,16 +394,16 @@ fn query_median_ref_data_bulk(deps: Deps, symbols: &[String]) -> StdResult StdResult { +fn query_deviation_ref(deps: Deps, symbol: &str) -> StdResult { if symbol == "USD" { - Ok(RefData::new(E0, Uint64::MAX, Uint64::zero())) + Ok(RefDeviationData::new(vec![E0], Uint64::MAX, Uint64::zero())) } else { let data = RefDeviationStore::load(deps.storage, symbol); data.ok_or(StdError::not_found("std_reference::state::RefData")) } } -fn query_deviation_ref_bulk(deps: Deps, symbols: &[String]) -> StdResult> { +fn query_deviation_ref_bulk(deps: Deps, symbols: &[String]) -> StdResult> { symbols .iter() .map(|symbol| query_deviation_ref(deps, symbol)) @@ -502,7 +491,10 @@ mod tests { // use cw_controllers::AdminError; - use crate::msg::ExecuteMsg::{AddRelayers, ForceRelay, Relay,RelayHistoricalMedian,RelayHistoricalDeviation, RemoveRelayers, UpdateAdmin, ForceRelayHistoricalMedian,ForceRelayHistoricalDeviation}; + use crate::msg::ExecuteMsg::{ + AddRelayers, ForceRelay, ForceRelayHistoricalDeviation, ForceRelayHistoricalMedian, + Relay, RelayHistoricalDeviation, RelayHistoricalMedian, RemoveRelayers, UpdateAdmin, + }; use super::*; @@ -533,12 +525,7 @@ mod tests { let err = execute(deps.as_mut(), env, info, msg); assert_eq!(err.is_err(), true); - assert_eq!( - err.err().unwrap(), - ContractError::Admin { - msg: String::from("ADMIN ONLY"), - } - ) + assert_eq!(err.unwrap_err(), ContractError::UnauthorizedAdmin {}) } #[test] @@ -604,12 +591,7 @@ mod tests { let msg = ExecuteMsg::MedianStatus { status: true }; let err = execute(deps.as_mut(), env, info, msg).unwrap_err(); - assert_eq!( - err, - ContractError::Admin { - msg: String::from("ADMIN ONLY"), - } - ) + assert_eq!(err, ContractError::UnauthorizedAdmin {}) } #[test] @@ -628,12 +610,7 @@ mod tests { relayers: vec![String::from("relayer_1")], }; let err = execute(deps.as_mut(), env, info, msg).unwrap_err(); - assert_eq!( - err, - ContractError::Admin { - msg: String::from("ADMIN ONLY"), - } - ) + assert_eq!(err, ContractError::UnauthorizedAdmin {}) } #[test] @@ -681,12 +658,7 @@ mod tests { let msg = RemoveRelayers { relayers }; let err = execute(deps.as_mut(), env, info, msg).unwrap_err(); - assert_eq!( - err, - ContractError::Admin { - msg: String::from("ADMIN ONLY"), - } - ); + assert_eq!(err, ContractError::UnauthorizedAdmin {}); } #[test] @@ -942,10 +914,7 @@ mod tests { // Check if relay was successful let err = query_median_ref_data_bulk(deps.as_ref(), &symbols.clone()).unwrap_err(); - assert_eq!( - err, - StdError::generic_err ("MEDIAN DISABLED") - ); + assert_eq!(err, StdError::generic_err("MEDIAN DISABLED")); } #[test] @@ -1027,14 +996,19 @@ mod tests { .into_iter() .map(|s| s.to_string()) .collect::>(); - let rates = [1000, 2000, 3000] + let deviations = [1000, 2000, 3000] .iter() .map(|r| Uint64::new(*r)) .collect::>(); + let symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(deviations.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = RelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), rates.clone()) - .collect::>(), + symbol_rates: symbol_rates.clone(), resolve_time: Uint64::from(10u64), request_id: Uint64::one(), }; @@ -1044,13 +1018,9 @@ mod tests { let reference_datas = query_deviation_ref_bulk(deps.as_ref(), &symbols.clone()).unwrap(); - let retrieved_rates = reference_datas - .clone() - .iter() - .map(|r| r.rate) - .collect::>(); - - assert_eq!(retrieved_rates, rates); + for (expected, actual) in symbol_rates.iter().zip(reference_datas.iter()) { + assert_eq!(expected.1, actual.rates) + } } #[test] @@ -1072,9 +1042,14 @@ mod tests { .map(|r| Uint64::new(*r)) .collect::>(); + let symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(deviations.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = ForceRelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), deviations.clone()) - .collect::>(), + symbol_rates: symbol_rates.clone(), resolve_time: Uint64::from(100u64), request_id: Uint64::from(2u64), }; @@ -1088,9 +1063,14 @@ mod tests { .map(|r| Uint64::new(*r)) .collect::>(); + let forced_deviation_symbol_rates: Vec<(String, Vec)> = symbols + .iter() + .zip(std::iter::repeat(forced_deviations.clone())) + .map(|(s, r)| (s.to_owned(), r)) + .collect(); + let msg = ForceRelayHistoricalDeviation { - symbol_rates: zip(symbols.clone(), forced_deviations.clone()) - .collect::>(), + symbol_rates: forced_deviation_symbol_rates.clone(), resolve_time: Uint64::from(10u64), request_id: Uint64::zero(), }; @@ -1100,13 +1080,12 @@ mod tests { let reference_datas = query_deviation_ref_bulk(deps.as_ref(), &symbols.clone()).unwrap(); - let retrieved_rates = reference_datas - .clone() + for (expected, actual) in forced_deviation_symbol_rates .iter() - .map(|r| r.rate) - .collect::>(); - - assert_eq!(retrieved_rates, forced_deviations); + .zip(reference_datas.iter()) + { + assert_eq!(expected.1, actual.rates) + } } #[test] @@ -1133,12 +1112,7 @@ mod tests { request_id: Uint64::zero(), }; let err = execute(deps.as_mut(), env, info, msg).unwrap_err(); - assert_eq!( - err, - ContractError::Unauthorized { - msg: String::from("Sender is not a relayer") - } - ); + assert_eq!(err, ContractError::UnauthorizedRelayer {}); } #[test] @@ -1229,24 +1203,16 @@ mod tests { request_id: Uint64::zero(), }; let err = execute(deps.as_mut(), env, info, msg).unwrap_err(); - assert_eq!( - err, - ContractError::Unauthorized { - msg: String::from("Sender is not a relayer") - } - ); + assert_eq!(err, ContractError::UnauthorizedRelayer {}); } } mod query { + use crate::msg::QueryMsg::{GetRef, GetReferenceData, GetReferenceDataBulk}; + use cosmwasm_std::from_binary; use std::iter::zip; use std::ops::Mul; - use cosmwasm_std::from_binary; - use cosmwasm_std::OverflowOperation::Add; - - use crate::msg::QueryMsg::{GetRef, GetReferenceData, GetReferenceDataBulk}; - use super::*; #[test] @@ -1266,12 +1232,7 @@ mod tests { assert_eq!(is_admin.is_err(), true,); - assert_eq!( - is_admin.err().unwrap(), - ContractError::Admin { - msg: String::from("ADMIN ONLY"), - } - ) + assert_eq!(is_admin.err().unwrap(), ContractError::UnauthorizedAdmin {}) } #[test] diff --git a/cosmwasm/contracts/price-feed/src/errors.rs b/cosmwasm/contracts/price-feed/src/errors.rs index e77be76..add2c06 100644 --- a/cosmwasm/contracts/price-feed/src/errors.rs +++ b/cosmwasm/contracts/price-feed/src/errors.rs @@ -7,11 +7,11 @@ pub enum ContractError { #[error("{0}")] Std(#[from] StdError), - #[error("Unauthorized: {msg}")] - Admin { msg: String }, + #[error("Unauthorized: sender is not an admin")] + UnauthorizedAdmin {}, - #[error("Unauthorized: {msg}")] - Unauthorized { msg: String }, + #[error("Unauthorized: sender is not relayer")] + UnauthorizedRelayer {}, #[error("Median is disabled")] MedianDisabled {}, diff --git a/cosmwasm/contracts/price-feed/src/msg.rs b/cosmwasm/contracts/price-feed/src/msg.rs index 61250a3..88cda86 100644 --- a/cosmwasm/contracts/price-feed/src/msg.rs +++ b/cosmwasm/contracts/price-feed/src/msg.rs @@ -1,9 +1,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Uint64; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use crate::state::{RefData, RefMedianData, ReferenceData}; +use crate::state::{RefData, RefDeviationData, RefMedianData, ReferenceData}; #[cw_serde] pub struct InstantiateMsg {} @@ -61,7 +59,7 @@ pub enum ExecuteMsg { }, // Relays a vector of symbols and their corresponding rates RelayHistoricalDeviation { - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, // Request ID of the results on Ojo request_id: Uint64, @@ -80,7 +78,7 @@ pub enum ExecuteMsg { }, // Relays a vector of symbols and their corresponding deviations ForceRelayHistoricalDeviation { - symbol_rates: Vec<(String, Uint64)>, + symbol_rates: Vec<(String, Vec)>, resolve_time: Uint64, // Request ID of the results on Ojo request_id: Uint64, @@ -135,14 +133,14 @@ pub enum QueryMsg { // Vector of Symbols to query symbols: Vec, }, - #[returns(RefData)] + #[returns(RefDeviationData)] // Returns the deviation RefData of a given symbol GetDeviationRef { // Symbol to query symbol: String, }, - #[returns(Vec < RefData >)] + #[returns(Vec < RefDeviationData >)] // Returns the deviation RefData of the given symbols GetDeviationRefBulk { // Vector of Symbols to query diff --git a/cosmwasm/contracts/price-feed/src/state.rs b/cosmwasm/contracts/price-feed/src/state.rs index 35df541..cad9237 100644 --- a/cosmwasm/contracts/price-feed/src/state.rs +++ b/cosmwasm/contracts/price-feed/src/state.rs @@ -1,6 +1,6 @@ use cosmwasm_schema::cw_serde; use cosmwasm_std::{Addr, StdResult, Storage, Uint256, Uint64}; -use secret_toolkit::serialization::{Bincode2, Json}; +use secret_toolkit::serialization::Bincode2; use secret_toolkit::storage::{Item, Keymap, Keyset, KeysetBuilder, WithoutIter}; use serde::{Deserialize, Serialize}; @@ -31,12 +31,11 @@ pub static REFDATA: Keymap = Keymap::new(REFDATA_KEY); // Used to store Deviation data pub const DEVIATIONDATA_KEY: &[u8] = b"deviationdata"; -pub static DEVIATIONDATA: Keymap = Keymap::new(DEVIATIONDATA_KEY); +pub static DEVIATIONDATA: Keymap = Keymap::new(DEVIATIONDATA_KEY); // Stores Median status -pub const MEDIANSTATUS_KEY: &[u8]= b"medianstatus"; -pub static MEDIANSTATUS: Item= Item::new(MEDIANSTATUS_KEY); - +pub const MEDIANSTATUS_KEY: &[u8] = b"medianstatus"; +pub static MEDIANSTATUS: Item = Item::new(MEDIANSTATUS_KEY); // Used to store Median data pub const MEDIANDATA_KEY: &[u8] = b"mediandata"; @@ -62,6 +61,26 @@ impl RefData { } } +#[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Default, schemars::JsonSchema)] +pub struct RefDeviationData { + // Rate of an asset relative to USD + pub rates: Vec, + // The resolve time of the request ID + pub resolve_time: Uint64, + // The request ID where the rate was derived from + pub request_id: Uint64, +} + +impl RefDeviationData { + pub fn new(rates: Vec, resolve_time: Uint64, request_id: Uint64) -> Self { + RefDeviationData { + rates, + resolve_time, + request_id, + } + } +} + pub struct RefStore {} impl RefStore { pub fn load(store: &dyn Storage, symbol: &str) -> Option { @@ -76,16 +95,15 @@ impl RefStore { // store deviation data pub struct RefDeviationStore {} impl RefDeviationStore { - pub fn load(store: &dyn Storage, symbol: &str) -> Option { + pub fn load(store: &dyn Storage, symbol: &str) -> Option { DEVIATIONDATA.get(store, &String::from(symbol.clone())) } - pub fn save(store: &mut dyn Storage, symbol: &str, data: &RefData) -> StdResult<()> { + pub fn save(store: &mut dyn Storage, symbol: &str, data: &RefDeviationData) -> StdResult<()> { DEVIATIONDATA.insert(store, &String::from(symbol.clone()), data) } } - #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Eq, Default, schemars::JsonSchema)] pub struct RefMedianData { // Median Rates of an asset relative to USD @@ -96,7 +114,7 @@ pub struct RefMedianData { pub request_id: Uint64, } -impl RefMedianData{ +impl RefMedianData { pub fn new(rates: Vec, resolve_time: Uint64, request_id: Uint64) -> Self { RefMedianData { rates, @@ -107,7 +125,7 @@ impl RefMedianData{ } // stores median data -pub struct RefMedianStore{} +pub struct RefMedianStore {} impl RefMedianStore { pub fn load(store: &dyn Storage, symbol: &str) -> Option { MEDIANDATA.get(store, &String::from(symbol.clone())) diff --git a/cw-relayer/config.toml b/cw-relayer/config.toml index 326695c..cb554e0 100644 --- a/cw-relayer/config.toml +++ b/cw-relayer/config.toml @@ -1,4 +1,4 @@ -contract_address = "secret1vghu442e4n90836xr40fccdgrypqt4spd8tdzw" +contract_address = "secret1aa8c3mxwu5kpcd8hlmkvjhzhqu37q8cj6eapyz" # relayer changes rpcs (event and query) in the order specified in config # query rpcs for prices @@ -18,7 +18,7 @@ query_timeout = "3000ms" max_retries = 1 timeout_height = 10 -resolve_duration = "1000ms" +resolve_duration = "20000ms" missed_threshold = 5 # default median data and ref request id at start/restart median_request_id = 1 @@ -30,8 +30,8 @@ ignore_median_errors= false gas_prices = "0.15uscrt" -code_hash = "125c44ec8884a412d596dbf40c59c14b010f6803eee0d3113f1e60a308cda126" -gas_limit = "102850" +code_hash = "287b53f3f5e70c3ec8a60aa0147374100d4a42770d6bae1d2fcac50bd7ce4691" +gas_limit = "855078" # restart config [restart] @@ -44,7 +44,7 @@ skip_error = false ### account & chain-id for the wasmd relayer account [account] address = "secret19uywplnd25gzxgc3t8pyqsl2tcse8heag2s6av" -chain_id = "pulsar-2" +chain_id = "pulsar-3" acc_prefix = "secret" ### keyring for the relayer account on the wasmd chain @@ -55,5 +55,5 @@ dir = "./" ### rpc endpoint for the wasm Chain [rpc] rpc_timeout = "5000ms" -query_endpoint = "grpcbin.pulsar.scrttestnet.com:9099" -tmrpc_endpoint = "https://rpc.pulsar.scrttestnet.com:443" +query_endpoint = "grpcbin.pulsar3.scrttestnet.com:9099" +tmrpc_endpoint = "https://rpc.pulsar3.scrttestnet.com:443" diff --git a/cw-relayer/relayer/client/client.go b/cw-relayer/relayer/client/client.go index 4e7e433..8161ea4 100644 --- a/cw-relayer/relayer/client/client.go +++ b/cw-relayer/relayer/client/client.go @@ -158,9 +158,10 @@ func (r *passReader) Read(p []byte) (n int, err error) { // BroadcastTx attempts to broadcast a signed transaction. If it fails, a few re-attempts // will be made until the transaction succeeds or ultimately times out or fails. -func (oc RelayerClient) BroadcastTx(clientCtx client.Context, nextBlockHeight, timeoutHeight int64, msgs ...sdk.Msg) error { +func (oc RelayerClient) BroadcastTx(clientCtx client.Context, timeoutDuration time.Duration, nextBlockHeight, timeoutHeight int64, msgs ...sdk.Msg) error { maxBlockHeight := nextBlockHeight + timeoutHeight lastCheckHeight := nextBlockHeight - 1 + start := time.Now() factory, err := oc.CreateTxFactory() if err != nil { @@ -175,6 +176,10 @@ func (oc RelayerClient) BroadcastTx(clientCtx client.Context, nextBlockHeight, t } if latestBlockHeight <= lastCheckHeight { + if time.Since(start).Seconds() >= timeoutDuration.Seconds() { + return fmt.Errorf("timeout duration exceeded") + } + continue } @@ -231,7 +236,7 @@ func (oc RelayerClient) BroadcastContractQuery( timeout time.Duration, queries ...SmartQuery, ) ([]QueryResponse, error) { - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() g, _ := errgroup.WithContext(ctx) diff --git a/cw-relayer/relayer/dep/msg.go b/cw-relayer/relayer/dep/msg.go index 06a4ec5..263949c 100644 --- a/cw-relayer/relayer/dep/msg.go +++ b/cw-relayer/relayer/dep/msg.go @@ -21,7 +21,7 @@ func (m SecretMsg) Serialize() []byte { return append(m.CodeHash, m.Msg...) } -func (msg MsgExecuteContract) ValidateBasic() error { +func (msg *MsgExecuteContract) ValidateBasic() error { if err := sdk.VerifyAddressFormat(msg.Sender); err != nil { return err } @@ -30,12 +30,12 @@ func (msg MsgExecuteContract) ValidateBasic() error { } if !msg.SentFunds.IsValid() { - return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "sentFunds") + return sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, "sentFunds") //nolint } return nil } -func (msg MsgExecuteContract) GetSigners() []sdk.AccAddress { +func (msg *MsgExecuteContract) GetSigners() []sdk.AccAddress { return []sdk.AccAddress{msg.Sender} } diff --git a/cw-relayer/relayer/dep/utils/types/msg.go b/cw-relayer/relayer/dep/utils/types/msg.go index 47473f2..15eaffd 100644 --- a/cw-relayer/relayer/dep/utils/types/msg.go +++ b/cw-relayer/relayer/dep/utils/types/msg.go @@ -21,11 +21,11 @@ func (msg RaAuthenticate) ValidateBasic() error { } if len(msg.Certificate) == 0 { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Authenticating certificate cannot be empty") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "Authenticating certificate cannot be empty") //nolint } if len(msg.Certificate) > MaxCertificateSize { - return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "certificate length too large") + return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "certificate length too large") //nolint } return nil diff --git a/cw-relayer/relayer/messages.go b/cw-relayer/relayer/messages.go index 1e0febc..6c47cc9 100644 --- a/cw-relayer/relayer/messages.go +++ b/cw-relayer/relayer/messages.go @@ -121,42 +121,42 @@ func generateContractRelayMsg(forceRelay bool, msgType MsgType, requestID uint64 RequestID: requestID, } - if msgType != RelayHistoricalMedian { + if msgType == RelayRate { for _, rate := range rates { msg.SymbolRates = append(msg.SymbolRates, [2]interface{}{rate.Denom, rate.Amount.Mul(RateFactor).TruncateInt().String()}) } - } - switch msgType { - case RelayRate: if forceRelay { msgData, err = json.Marshal(MsgForceRelay{Relay: msg}) } else { msgData, err = json.Marshal(MsgRelay{Relay: msg}) } - case RelayHistoricalMedian: - // collect denom's medians - medianRates := map[string][]string{} + return + } else { + symbolRates := map[string][]string{} for _, rate := range rates { - medianRates[rate.Denom] = append(medianRates[rate.Denom], rate.Amount.Mul(RateFactor).TruncateInt().String()) + symbolRates[rate.Denom] = append(symbolRates[rate.Denom], rate.Amount.Mul(RateFactor).TruncateInt().String()) } - for denom, medians := range medianRates { + for denom, medians := range symbolRates { msg.SymbolRates = append(msg.SymbolRates, [2]interface{}{denom, medians}) } - if forceRelay { - msgData, err = json.Marshal(MsgForceRelayHistoricalMedian{Relay: msg}) - } else { - msgData, err = json.Marshal(MsgRelayHistoricalMedian{Relay: msg}) - } - - case RelayHistoricalDeviation: - if forceRelay { - msgData, err = json.Marshal(MsgForceRelayHistoricalDeviation{Relay: msg}) - } else { - msgData, err = json.Marshal(MsgRelayHistoricalDeviation{Relay: msg}) + switch msgType { + case RelayHistoricalMedian: + if forceRelay { + msgData, err = json.Marshal(MsgForceRelayHistoricalMedian{Relay: msg}) + } else { + msgData, err = json.Marshal(MsgRelayHistoricalMedian{Relay: msg}) + } + + case RelayHistoricalDeviation: + if forceRelay { + msgData, err = json.Marshal(MsgForceRelayHistoricalDeviation{Relay: msg}) + } else { + msgData, err = json.Marshal(MsgRelayHistoricalDeviation{Relay: msg}) + } } } diff --git a/cw-relayer/relayer/relayer.go b/cw-relayer/relayer/relayer.go index d5f8328..af1e2be 100644 --- a/cw-relayer/relayer/relayer.go +++ b/cw-relayer/relayer/relayer.go @@ -475,8 +475,8 @@ func (r *Relayer) tick(ctx context.Context) error { executeMsgs[i] = &executeMsg } - logs.Msg("broadcasting execute to contract") - if err := r.relayerClient.BroadcastTx(*clientCtx, nextBlockHeight, r.timeoutHeight, executeMsgs...); err != nil { + logs.Msg("broadcasting tx") + if err := r.relayerClient.BroadcastTx(*clientCtx, r.resolveDuration, nextBlockHeight, r.timeoutHeight, executeMsgs...); err != nil { r.missedCounter += 1 return err } diff --git a/cw-relayer/relayer/relayer_test.go b/cw-relayer/relayer/relayer_test.go index c0d0ce9..1d0b543 100644 --- a/cw-relayer/relayer/relayer_test.go +++ b/cw-relayer/relayer/relayer_test.go @@ -1,6 +1,10 @@ package relayer import ( + "encoding/json" + "fmt" + "math/rand" + "strconv" "testing" "github.com/cosmos/cosmos-sdk/types" @@ -19,31 +23,120 @@ func TestServiceTestSuite(t *testing.T) { func (rts *RelayerTestSuite) TestStop() {} -func (rts *RelayerTestSuite) Test_generateContractMsg() { +func (rts *RelayerTestSuite) Test_generateRelayMsg() { exchangeRates := types.DecCoins{ - types.NewDecCoinFromDec("atom", types.MustNewDecFromStr("1.23456789")), + types.NewDecCoinFromDec("atom", types.MustNewDecFromStr("1.13456789")), types.NewDecCoinFromDec("umee", types.MustNewDecFromStr("1.23456789")), - types.NewDecCoinFromDec("juno", types.MustNewDecFromStr("1.23456789")), + types.NewDecCoinFromDec("juno", types.MustNewDecFromStr("1.33456789")), } - rts.Run("Relay msg", func() { - msg, err := generateContractRelayMsg(false, 1, 1, 1, exchangeRates) - rts.Require().NoError(err) + testCases := []struct { + tc string + forceRelay bool + msgType MsgType + }{ + { + tc: "Relay msg", + forceRelay: false, + msgType: RelayRate, + }, + { + tc: "Force Relay msg", + forceRelay: true, + msgType: RelayRate, + }, + } + + for _, tc := range testCases { + rts.Run( + tc.tc, func() { + msg, err := generateContractRelayMsg(tc.forceRelay, tc.msgType, 0, 0, exchangeRates) + rts.Require().NoError(err) - // price * 10**9 (USD factor in contract) - expectedRes := "{\"relay\":{\"symbol_rates\":[[\"atom\",\"1234567890\"],[\"umee\",\"1234567890\"],[\"juno\",\"1234567890\"]],\"resolve_time\":\"1\",\"request_id\":\"1\"}}" - msgStr := string(msg) + var expectedMsg map[string]Msg + err = json.Unmarshal(msg, &expectedMsg) + rts.Require().NoError(err) - rts.Require().Equal(expectedRes, msgStr) - }) + msgKey := tc.msgType.String() + if tc.forceRelay { + msgKey = fmt.Sprintf("force_%s", tc.msgType.String()) + } - rts.Run("Force Relay msg", func() { - msg, err := generateContractRelayMsg(true, 1, 1, 1, exchangeRates) - rts.Require().NoError(err) + rates := expectedMsg[msgKey].SymbolRates + rts.Require().NotZero(len(rates)) + for i, rate := range rates { + rts.Require().Equal(rate[0], exchangeRates[i].Denom) + rts.Require().Equal(rate[1], exchangeRates[i].Amount.Mul(RateFactor).TruncateInt().String()) + } + }, + ) + } +} - expectedRes := "{\"force_relay\":{\"symbol_rates\":[[\"atom\",\"1234567890\"],[\"umee\",\"1234567890\"],[\"juno\",\"1234567890\"]],\"resolve_time\":\"1\",\"request_id\":\"1\"}}" - msgStr := string(msg) +func (rts *RelayerTestSuite) Test_generateMedianRelayMsg() { + var exchangeRates types.DecCoins + rateMap := map[string][]interface{}{} + for _, denom := range []string{"atom", "umee", "juno"} { + for i := 0; i < 10; i++ { + price := rand.Float64() + if i%2 == 1 { + // to have prices above 1 + price = price * 100000 + } - rts.Require().Equal(expectedRes, msgStr) - }) + priceDec := types.MustNewDecFromStr(strconv.FormatFloat(price, 'f', 9, 64)) + exchangeRates = append(exchangeRates, types.NewDecCoinFromDec(denom, priceDec)) + rateMap[denom] = append(rateMap[denom], priceDec.Mul(RateFactor).TruncateInt().String()) + } + } + + testCases := []struct { + tc string + forceRelay bool + msgType MsgType + }{ + { + tc: "Median Relay msg", + forceRelay: false, + msgType: RelayHistoricalMedian, + }, + { + tc: "Median Force Relay msg", + forceRelay: true, + msgType: RelayHistoricalMedian, + }, + { + tc: "Deviation Relay msg", + forceRelay: false, + msgType: RelayHistoricalDeviation, + }, + { + tc: "Deviation Force Relay msg", + forceRelay: false, + msgType: RelayHistoricalDeviation, + }, + } + + for _, tc := range testCases { + rts.Run(tc.tc, func() { + msg, err := generateContractRelayMsg(tc.forceRelay, tc.msgType, 0, 0, exchangeRates) + rts.Require().NoError(err) + + var expectedMsg map[string]Msg + err = json.Unmarshal(msg, &expectedMsg) + rts.Require().NoError(err) + + key := tc.msgType.String() + if tc.forceRelay { + key = fmt.Sprintf("force_%s", key) + } + + rates := expectedMsg[key].SymbolRates + rts.Require().Len(rates, 3) + + for _, rate := range rates { + rts.Require().Equal(rate[1], rateMap[rate[0].(string)]) + } + }) + } } diff --git a/scripts/deploy_contract.sh b/scripts/deploy_contract.sh index 5df44ae..4721608 100755 --- a/scripts/deploy_contract.sh +++ b/scripts/deploy_contract.sh @@ -1,36 +1,29 @@ BINARY=secretcli -CHAINID_1="pulsar-2" +CHAINID_1="pulsar-3" CONTRACT_PATH=./cosmwasm/artifacts/std_reference.wasm -RPC="https://rpc.testnet.secretsaturn.net" +RPC="https://rpc.pulsar3.scrttestnet.com:443" NODE="--node $RPC" -TXFLAG="$NODE --chain-id $CHAINID_1 --gas-prices 1uscrt --gas-adjustment 1.3" +TXFLAG="$NODE --chain-id $CHAINID_1 --gas-prices 1uscrt --gas-adjustment 1.3 --broadcast-mode block --gas auto" -export DEMOWALLET=$($BINARY keys show relayer -a --keyring-backend=test --keyring-dir=./relayer-data/ ) && echo $DEMOWALLET; -$BINARY query wasm list-code $NODE +export DEMOWALLET=$($BINARY keys show relayer2 -a --keyring-backend=test ) && echo $DEMOWALLET; # deploy smart contract -$BINARY tx compute store $CONTRACT_PATH --from $DEMOWALLET --keyring-backend=test --keyring-dir=./cw-relayer/data/ $TXFLAG -y -sleep 5 - -$BINARY tx compute instantiate 19480 '{}' --label=newtest --from $DEMOWALLET --keyring-backend=test --keyring-dir=./cw-relayer/data/ -y -sleep 5 +$BINARY tx compute store $CONTRACT_PATH --from $DEMOWALLET --keyring-backend=test $TXFLAG -y #instantiate contract -$BINARY tx compute instantiate 1 '{}' --label=newthings --from $DEMOWALLET --keyring-backend=test --keyring-dir=./cw-relayer/newrelayerdata/ --sign-mode=direct $TXFLAG -y -sleep 5 +$BINARY tx compute instantiate 1 '{}' --label=test --from $DEMOWALLET --keyring-backend=test -y -## query contract address -CONTRACT=$($BINARY query compute list-contract-by-code "19480" $NODE --output json | jq -r '.[0].contract_address') +# query contract address +CONTRACT=$($BINARY query compute list-contract-by-code "1" $NODE --output json | jq -r '.[0].contract_address') echo $CONTRACT -#sample +#adding relayer ADD_RELAYERS='{"add_relayers": {"relayers": ["secret19uywplnd25gzxgc3t8pyqsl2tcse8heag2s6av"]}}' -$BINARY tx compute execute $CONTRACT "$ADD_RELAYERS" --keyring-dir=./relayer-data --keyring-backend=test --from $DEMOWALLET --dry-run -y -sleep 5 +$BINARY tx compute execute $CONTRACT "$ADD_RELAYERS" --from $DEMOWALLET --keyring-backend=test $TXFLAG -y +#sample price tx RELAY='{"force_relay": {"symbol_rates": [["ATOM","14"]], "resolve_time":"10", "request_id":"2"}}' -$BINARY tx compute execute $CONTRACT "$RELAY" --keyring-backend=test --keyring-dir=./cw-relayer/data/ --sign-mode=direct --from $DEMOWALLET $TXFLAG --offline -sleep 5 +$BINARY tx compute execute $CONTRACT "$RELAY" --keyring-backend=test --sign-mode=direct --from $DEMOWALLET $TXFLAG QUERY='{"get_ref": {"symbol": "ATOM"}}' $BINARY query compute query $CONTRACT "$QUERY" $NODE --output json \ No newline at end of file