diff --git a/Cargo.lock b/Cargo.lock index c9f87aa4..7c98ea8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,7 @@ dependencies = [ "cw2", "derivative", "mesh-apis", + "mesh-bindings", "mesh-burn", "mesh-simple-price-feed", "schemars", @@ -736,6 +737,7 @@ dependencies = [ "cw2", "derivative", "mesh-apis", + "mesh-bindings", "schemars", "serde", "sylvia", @@ -1188,8 +1190,7 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "sylvia" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64c8e892525ec035e5bdbeceec19309b1534734da7ff7bc69e9f639b077c497" +source = "git+https://github.com/CosmWasm/sylvia?branch=jawoznia/cosmwasm1/map_err_on_into_response#a5d3546eb287e3e7f003251c529ff3401784e1bb" dependencies = [ "anyhow", "cosmwasm-schema", @@ -1207,8 +1208,7 @@ dependencies = [ [[package]] name = "sylvia-derive" version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae5e0f41752efba2c6895514fa4caae742f69a2a73b4790bb6e365400c563bc1" +source = "git+https://github.com/CosmWasm/sylvia?branch=jawoznia/cosmwasm1/map_err_on_into_response#a5d3546eb287e3e7f003251c529ff3401784e1bb" dependencies = [ "convert_case", "itertools 0.12.1", diff --git a/Cargo.toml b/Cargo.toml index b15060e5..e5384b60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,58 +1,65 @@ [workspace] -members = ["packages/*", "contracts/provider/*", "contracts/consumer/*", "contracts/osmosis-price-provider"] +members = [ + "packages/*", + "contracts/provider/*", + "contracts/consumer/*", + "contracts/osmosis-price-provider", +] resolver = "2" [workspace.package] -edition = "2021" -version = "0.10.0-alpha.1" -license = "MIT" -repository = "https://github.com/osmosis-labs/mesh-security" +edition = "2021" +version = "0.10.0-alpha.1" +license = "MIT" +repository = "https://github.com/osmosis-labs/mesh-security" [workspace.dependencies] -mesh-apis = { path = "./packages/apis" } -mesh-bindings = { path = "./packages/bindings" } -mesh-burn = { path = "./packages/burn" } -mesh-sync = { path = "./packages/sync" } +mesh-apis = { path = "./packages/apis" } +mesh-bindings = { path = "./packages/bindings" } +mesh-burn = { path = "./packages/burn" } +mesh-sync = { path = "./packages/sync" } mesh-virtual-staking-mock = { path = "./packages/virtual-staking-mock" } -mesh-vault = { path = "./contracts/provider/vault" } -mesh-external-staking = { path = "./contracts/provider/external-staking" } -mesh-native-staking = { path = "./contracts/provider/native-staking" } -mesh-native-staking-proxy = { path = "./contracts/provider/native-staking-proxy" } - -mesh-converter = { path = "./contracts/consumer/converter" } -mesh-simple-price-feed = { path = "./contracts/consumer/simple-price-feed" } -mesh-virtual-staking = { path = "./contracts/consumer/virtual-staking" } - -sylvia = "0.10.1" -cosmwasm-schema = "1.5.4" -cosmwasm-std = { version = "1.5.4", features = ["ibc3", "cosmwasm_1_3"] } -cw-storage-plus = "1.2.0" -cw-utils = "1.0.3" -cw2 = "1.1.2" -osmosis-std = "0.20.1" -schemars = "0.8.17" -serde = { version = "1.0.199", default-features = false, features = ["derive"] } -thiserror = "1.0.59" +mesh-vault = { path = "./contracts/provider/vault" } +mesh-external-staking = { path = "./contracts/provider/external-staking" } +mesh-native-staking = { path = "./contracts/provider/native-staking" } +mesh-native-staking-proxy = { path = "./contracts/provider/native-staking-proxy" } + +mesh-converter = { path = "./contracts/consumer/converter" } +mesh-simple-price-feed = { path = "./contracts/consumer/simple-price-feed" } +mesh-virtual-staking = { path = "./contracts/consumer/virtual-staking" } + +sylvia = { git = "https://github.com/CosmWasm/sylvia", branch = "jawoznia/cosmwasm1/map_err_on_into_response", features = [ + "mt", +] } +cosmwasm-schema = "1.5.4" +cosmwasm-std = { version = "1.5.4", features = ["ibc3", "cosmwasm_1_3"] } +cw-storage-plus = "1.2.0" +cw-utils = "1.0.3" +cw2 = "1.1.2" +osmosis-std = "0.20.1" +schemars = "0.8.17" +serde = { version = "1.0.199", default-features = false, features = ["derive"] } +thiserror = "1.0.59" semver = "1.0.22" itertools = "0.12.1" # dev deps -anyhow = "1" +anyhow = "1" cw-multi-test = "0.20" -derivative = "2" -test-case = "3.3.1" +derivative = "2" +test-case = "3.3.1" [profile.release] -codegen-units = 1 -debug = false +codegen-units = 1 +debug = false debug-assertions = false -lto = true -panic = 'abort' -rpath = false -opt-level = 3 -overflow-checks = true +lto = true +panic = 'abort' +rpath = false +opt-level = 3 +overflow-checks = true [profile.release.package.mesh-vault] codegen-units = 1 -incremental = false +incremental = false diff --git a/contracts/consumer/converter/Cargo.toml b/contracts/consumer/converter/Cargo.toml index 547f896d..c60f0af3 100644 --- a/contracts/consumer/converter/Cargo.toml +++ b/contracts/consumer/converter/Cargo.toml @@ -3,8 +3,8 @@ name = "mesh-converter" description = "IBC connector on the Consumer side, converting their IBC messages into native tokens for virtual staking" version = { workspace = true } edition = { workspace = true } -license = { workspace = true } -repository = { workspace = true } +license = { workspace = true } +repository = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -19,28 +19,29 @@ library = [] mt = ["library", "sylvia/mt"] [dependencies] -mesh-apis = { workspace = true } +mesh-apis = { workspace = true } +mesh-bindings = { workspace = true } -sylvia = { workspace = true } -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw-storage-plus = { workspace = true } -cw2 = { workspace = true } -cw-utils = { workspace = true } +sylvia = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw-utils = { workspace = true } -schemars = { workspace = true } -serde = { workspace = true } -thiserror = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] -mesh-burn = { workspace = true } +mesh-burn = { workspace = true } mesh-simple-price-feed = { workspace = true, features = ["mt"] } cw-multi-test = { workspace = true } -test-case = { workspace = true } -derivative = { workspace = true } -anyhow = { workspace = true } +test-case = { workspace = true } +derivative = { workspace = true } +anyhow = { workspace = true } [[bin]] name = "schema" -doc = false +doc = false diff --git a/contracts/consumer/converter/src/contract.rs b/contracts/consumer/converter/src/contract.rs index 294adf4a..20203484 100644 --- a/contracts/consumer/converter/src/contract.rs +++ b/contracts/consumer/converter/src/contract.rs @@ -1,5 +1,7 @@ use cosmwasm_std::{ - ensure_eq, to_json_binary, Addr, BankMsg, Coin, CosmosMsg, Decimal, Deps, DepsMut, Event, Fraction, MessageInfo, Reply, Response, StdError, SubMsg, SubMsgResponse, Uint128, Validator, WasmMsg + ensure_eq, to_json_binary, Addr, BankMsg, Coin, CosmosMsg, Decimal, Deps, DepsMut, Event, + Fraction, MessageInfo, Reply, Response, StdError, SubMsg, SubMsgResponse, Uint128, Validator, + WasmMsg, }; use cw2::set_contract_version; use cw_storage_plus::Item; @@ -22,6 +24,16 @@ pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); const REPLY_ID_INSTANTIATE: u64 = 1; +#[cfg(not(any(test, feature = "mt")))] +pub type ConverterCustomMsg = cosmwasm_std::Empty; +#[cfg(any(test, feature = "mt"))] +pub type ConverterCustomMsg = mesh_bindings::VirtualStakeCustomMsg; + +#[cfg(not(any(test, feature = "mt")))] +pub type ConverterCustomQuery = cosmwasm_std::Empty; +#[cfg(any(test, feature = "mt"))] +pub type ConverterCustomQuery = mesh_bindings::VirtualStakeCustomQuery; + pub struct ConverterContract<'a> { pub config: Item<'a, Config>, pub virtual_stake: Item<'a, Addr>, @@ -31,6 +43,8 @@ pub struct ConverterContract<'a> { #[contract] #[sv::error(ContractError)] #[sv::messages(converter_api as ConverterApi)] +/// Workaround for lack of support in communication `Empty` <-> `Custom` Contracts. +#[sv::custom(query=ConverterCustomQuery, msg=ConverterCustomMsg)] impl ConverterContract<'_> { pub const fn new() -> Self { Self { @@ -49,7 +63,7 @@ impl ConverterContract<'_> { #[sv::msg(instantiate)] pub fn instantiate( &self, - ctx: InstantiateCtx, + ctx: InstantiateCtx, price_feed: String, discount: Decimal, remote_denom: String, @@ -92,7 +106,11 @@ impl ConverterContract<'_> { } #[sv::msg(reply)] - fn reply(&self, ctx: ReplyCtx, reply: Reply) -> Result { + fn reply( + &self, + ctx: ReplyCtx, + reply: Reply, + ) -> Result { match reply.id { REPLY_ID_INSTANTIATE => self.reply_init_callback(ctx.deps, reply.result.unwrap()), _ => Err(ContractError::InvalidReplyId(reply.id)), @@ -102,7 +120,7 @@ impl ConverterContract<'_> { /// Store virtual staking address fn reply_init_callback( &self, - deps: DepsMut, + deps: DepsMut, reply: SubMsgResponse, ) -> Result { let init_data = parse_instantiate_response_data(&reply.data.unwrap())?; @@ -116,7 +134,7 @@ impl ConverterContract<'_> { #[sv::msg(exec)] fn test_stake( &self, - ctx: ExecCtx, + ctx: ExecCtx, validator: String, stake: Coin, ) -> Result { @@ -137,7 +155,7 @@ impl ConverterContract<'_> { #[sv::msg(exec)] fn test_unstake( &self, - ctx: ExecCtx, + ctx: ExecCtx, validator: String, unstake: Coin, ) -> Result { @@ -158,7 +176,7 @@ impl ConverterContract<'_> { #[sv::msg(exec)] fn test_burn( &self, - ctx: ExecCtx, + ctx: ExecCtx, validators: Vec, burn: Coin, ) -> Result { @@ -175,7 +193,7 @@ impl ConverterContract<'_> { } #[sv::msg(query)] - fn config(&self, ctx: QueryCtx) -> Result { + fn config(&self, ctx: QueryCtx) -> Result { let config = self.config.load(ctx.deps.storage)?; let virtual_staking = self.virtual_stake.load(ctx.deps.storage)?.into_string(); Ok(ConfigResponse { @@ -189,7 +207,7 @@ impl ConverterContract<'_> { /// It is pulled out into a method, so it can also be called by test_stake for testing pub(crate) fn stake( &self, - deps: DepsMut, + deps: DepsMut, validator: String, stake: Coin, ) -> Result { @@ -213,7 +231,7 @@ impl ConverterContract<'_> { /// It is pulled out into a method, so it can also be called by test_unstake for testing pub(crate) fn unstake( &self, - deps: DepsMut, + deps: DepsMut, validator: String, unstake: Coin, ) -> Result { @@ -237,7 +255,7 @@ impl ConverterContract<'_> { /// It is pulled out into a method, so it can also be called by test_burn for testing pub(crate) fn burn( &self, - deps: DepsMut, + deps: DepsMut, validators: &[String], burn: Coin, ) -> Result { @@ -260,7 +278,11 @@ impl ConverterContract<'_> { Ok(Response::new().add_message(msg).add_event(event)) } - fn normalize_price(&self, deps: Deps, amount: Coin) -> Result { + fn normalize_price( + &self, + deps: Deps, + amount: Coin, + ) -> Result { let config = self.config.load(deps.storage)?; ensure_eq!( config.remote_denom, @@ -278,7 +300,8 @@ impl ConverterContract<'_> { use sylvia::types::Remote; // NOTE: Jan, this feels hacky... I'm not sure if this is the right way to do it // Also, I am sticking in a random error type here, not what I will get (which is unknown) - let remote = Remote::<&dyn price_feed_api::PriceFeedApi>::new(config.price_feed); + let remote = + Remote::<&dyn price_feed_api::PriceFeedApi>::new(config.price_feed); let price = remote.querier(&deps.querier).price()?.native_per_foreign; let converted = (amount.amount * price) * config.price_adjustment; @@ -288,7 +311,11 @@ impl ConverterContract<'_> { }) } - fn invert_price(&self, deps: Deps, amount: Coin) -> Result { + fn invert_price( + &self, + deps: Deps, + amount: Coin, + ) -> Result { let config = self.config.load(deps.storage)?; ensure_eq!( config.local_denom, @@ -305,7 +332,8 @@ impl ConverterContract<'_> { use sylvia::types::Remote; // NOTE: Jan, this feels hacky... I'm not sure if this is the right way to do it // Also, I am sticking in a random error type here, not what I will get (which is unknown) - let remote = Remote::<&dyn price_feed_api::PriceFeedApi>::new(config.price_feed); + let remote = + Remote::<&dyn price_feed_api::PriceFeedApi>::new(config.price_feed); let price = remote.querier(&deps.querier).price()?.native_per_foreign; let converted = (amount.amount * price.inv().ok_or(ContractError::InvalidPrice {})?) * config @@ -321,7 +349,7 @@ impl ConverterContract<'_> { pub(crate) fn transfer_rewards( &self, - deps: Deps, + deps: Deps, recipient: String, rewards: Coin, ) -> Result { @@ -347,7 +375,11 @@ impl ConverterContract<'_> { Ok(msg.into()) } - fn ensure_authorized(&self, deps: &DepsMut, info: &MessageInfo) -> Result<(), ContractError> { + fn ensure_authorized( + &self, + deps: &DepsMut, + info: &MessageInfo, + ) -> Result<(), ContractError> { let virtual_stake = self.virtual_stake.load(deps.storage)?; ensure_eq!(info.sender, virtual_stake, ContractError::Unauthorized {}); @@ -362,7 +394,7 @@ impl ConverterApi for ConverterContract<'_> { /// stakers who staked on this validator. This is tracked on the provider, so we send an IBC packet there. fn distribute_reward( &self, - mut ctx: ExecCtx, + mut ctx: ExecCtx, validator: String, ) -> Result { self.ensure_authorized(&ctx.deps, &ctx.info)?; @@ -387,7 +419,7 @@ impl ConverterApi for ConverterContract<'_> { /// in the native staking denom. fn distribute_rewards( &self, - mut ctx: ExecCtx, + mut ctx: ExecCtx, payments: Vec, ) -> Result { self.ensure_authorized(&ctx.deps, &ctx.info)?; @@ -427,7 +459,7 @@ impl ConverterApi for ConverterContract<'_> { #[allow(clippy::too_many_arguments)] fn valset_update( &self, - ctx: ExecCtx, + ctx: ExecCtx, additions: Vec, removals: Vec, updated: Vec, diff --git a/contracts/consumer/simple-price-feed/Cargo.toml b/contracts/consumer/simple-price-feed/Cargo.toml index d19c68b7..3122ac0d 100644 --- a/contracts/consumer/simple-price-feed/Cargo.toml +++ b/contracts/consumer/simple-price-feed/Cargo.toml @@ -3,8 +3,8 @@ name = "mesh-simple-price-feed" description = "Returns a fixed price for assets to the converter contract - for tests or gov-defined prices" version = { workspace = true } edition = { workspace = true } -license = { workspace = true } -repository = { workspace = true } +license = { workspace = true } +repository = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [lib] @@ -19,25 +19,26 @@ library = [] mt = ["library", "sylvia/mt"] [dependencies] -mesh-apis = { workspace = true } +mesh-apis = { workspace = true } +mesh-bindings = { workspace = true } sylvia = { workspace = true } -cosmwasm-schema = { workspace = true } -cosmwasm-std = { workspace = true } -cw-storage-plus = { workspace = true } -cw2 = { workspace = true } -cw-utils = { workspace = true } +cosmwasm-schema = { workspace = true } +cosmwasm-std = { workspace = true } +cw-storage-plus = { workspace = true } +cw2 = { workspace = true } +cw-utils = { workspace = true } -schemars = { workspace = true } -serde = { workspace = true } -thiserror = { workspace = true } +schemars = { workspace = true } +serde = { workspace = true } +thiserror = { workspace = true } [dev-dependencies] cw-multi-test = { workspace = true } -test-case = { workspace = true } -derivative = { workspace = true } -anyhow = { workspace = true } +test-case = { workspace = true } +derivative = { workspace = true } +anyhow = { workspace = true } [[bin]] name = "schema" -doc = false +doc = false diff --git a/contracts/consumer/simple-price-feed/src/contract.rs b/contracts/consumer/simple-price-feed/src/contract.rs index 59896fc4..06aedf11 100644 --- a/contracts/consumer/simple-price-feed/src/contract.rs +++ b/contracts/consumer/simple-price-feed/src/contract.rs @@ -14,6 +14,16 @@ use crate::state::Config; pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME"); pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); +#[cfg(not(any(test, feature = "mt")))] +pub type PriceFeedCustomMsg = cosmwasm_std::Empty; +#[cfg(any(test, feature = "mt"))] +pub type PriceFeedCustomMsg = mesh_bindings::VirtualStakeCustomMsg; + +#[cfg(not(any(test, feature = "mt")))] +pub type PriceFeedCustomQuery = cosmwasm_std::Empty; +#[cfg(any(test, feature = "mt"))] +pub type PriceFeedCustomQuery = mesh_bindings::VirtualStakeCustomQuery; + pub struct SimplePriceFeedContract<'a> { pub config: Item<'a, Config>, } @@ -21,7 +31,11 @@ pub struct SimplePriceFeedContract<'a> { #[cfg_attr(not(feature = "library"), sylvia::entry_points)] #[contract] #[sv::error(ContractError)] -#[sv::messages(price_feed_api as PriceFeedApi)] +#[sv::messages(price_feed_api as PriceFeedApi: custom(msg, query))] +// #[cfg_attr(any(test, feature = "mt"), sv::messages(price_feed_api as PriceFeedApi: custom(msg, query)))] +// #[cfg_attr(not(any(test, feature = "mt")), sv::messages(price_feed_api as PriceFeedApi))] +/// Workaround for lack of support in communication `Empty` <-> `Custom` Contracts. +#[sv::custom(query=PriceFeedCustomQuery, msg=PriceFeedCustomMsg)] impl SimplePriceFeedContract<'_> { pub const fn new() -> Self { Self { @@ -34,10 +48,10 @@ impl SimplePriceFeedContract<'_> { #[sv::msg(instantiate)] pub fn instantiate( &self, - ctx: InstantiateCtx, + ctx: InstantiateCtx, native_per_foreign: Decimal, owner: Option, - ) -> Result { + ) -> Result, ContractError> { nonpayable(&ctx.info)?; let owner = match owner { Some(owner) => ctx.deps.api.addr_validate(&owner)?, @@ -56,9 +70,9 @@ impl SimplePriceFeedContract<'_> { #[sv::msg(exec)] fn update_price( &self, - ctx: ExecCtx, + ctx: ExecCtx, native_per_foreign: Decimal, - ) -> Result { + ) -> Result, ContractError> { nonpayable(&ctx.info)?; let mut config = self.config.load(ctx.deps.storage)?; @@ -76,7 +90,7 @@ impl SimplePriceFeedContract<'_> { } #[sv::msg(query)] - fn config(&self, ctx: QueryCtx) -> Result { + fn config(&self, ctx: QueryCtx) -> Result { let config = self.config.load(ctx.deps.storage)?; Ok(ConfigResponse { owner: config.owner.into_string(), diff --git a/contracts/consumer/virtual-staking/src/contract.rs b/contracts/consumer/virtual-staking/src/contract.rs index 41f24682..42a53555 100644 --- a/contracts/consumer/virtual-staking/src/contract.rs +++ b/contracts/consumer/virtual-staking/src/contract.rs @@ -360,7 +360,6 @@ impl VirtualStakingApi for VirtualStakingContract<'_> { fn bond( &self, ctx: ExecCtx, - validator: String, amount: Coin, ) -> Result, Self::Error> {