Skip to content

Commit

Permalink
Merge branch 'main' into vuong/band-oracle
Browse files Browse the repository at this point in the history
  • Loading branch information
vuong177 committed Sep 9, 2024
2 parents c0780ce + 073dae6 commit 79bd951
Show file tree
Hide file tree
Showing 39 changed files with 3,081 additions and 863 deletions.
324 changes: 162 additions & 162 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ mesh-bindings = { path = "./packages/bindings" }
mesh-burn = { path = "./packages/burn" }
mesh-price-feed = { path = "./packages/price-feed" }
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" }
Expand Down
3 changes: 3 additions & 0 deletions contracts/consumer/converter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ fake-custom = [ "mesh-simple-price-feed/fake-custom" ]
[dependencies]
mesh-apis = { workspace = true }
mesh-bindings = { workspace = true }
mesh-sync = { workspace = true }
mesh-virtual-staking = { workspace = true }

sylvia = { workspace = true }
cosmwasm-schema = { workspace = true }
Expand All @@ -38,6 +40,7 @@ thiserror = { workspace = true }
[dev-dependencies]
mesh-burn = { workspace = true }
mesh-simple-price-feed = { workspace = true, features = ["mt"] }
mesh-virtual-staking = { workspace = true, features = ["mt"] }

cw-multi-test = { workspace = true }
test-case = { workspace = true }
Expand Down
76 changes: 66 additions & 10 deletions contracts/consumer/converter/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,7 +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,
Fraction, IbcMsg, MessageInfo, Reply, Response, StdError, SubMsg, SubMsgResponse, Uint128,
Validator, WasmMsg,
};
use cw2::set_contract_version;
use cw_storage_plus::Item;
Expand All @@ -15,7 +15,9 @@ use mesh_apis::price_feed_api;
use mesh_apis::virtual_staking_api;

use crate::error::ContractError;
use crate::ibc::{make_ibc_packet, valset_update_msg, IBC_CHANNEL};
use crate::ibc::{
make_ibc_packet, packet_timeout_internal_unstake, valset_update_msg, IBC_CHANNEL,
};
use crate::msg::ConfigResponse;
use crate::state::Config;

Expand Down Expand Up @@ -71,7 +73,9 @@ impl ConverterContract<'_> {
discount: Decimal,
remote_denom: String,
virtual_staking_code_id: u64,
tombstoned_unbond_enable: bool,
admin: Option<String>,
max_retrieve: u32,
) -> Result<custom::Response, ContractError> {
nonpayable(&ctx.info)?;
// validate args
Expand All @@ -95,11 +99,15 @@ impl ConverterContract<'_> {
ctx.deps.api.addr_validate(admin)?;
}

let msg = to_json_binary(&mesh_virtual_staking::contract::sv::InstantiateMsg {
max_retrieve,
tombstoned_unbond_enable,
})?;
// Instantiate virtual staking contract
let init_msg = WasmMsg::Instantiate {
admin,
code_id: virtual_staking_code_id,
msg: b"{}".into(),
msg,
funds: vec![],
label: format!("Virtual Staking: {}", &config.remote_denom),
};
Expand Down Expand Up @@ -138,17 +146,18 @@ impl ConverterContract<'_> {
fn test_stake(
&self,
ctx: ExecCtx<custom::ConverterQuery>,
delegator: String,
validator: String,
stake: Coin,
) -> Result<custom::Response, ContractError> {
#[cfg(any(test, feature = "mt"))]
{
// This can only ever be called in tests
self.stake(ctx.deps, validator, stake)
self.stake(ctx.deps, delegator, validator, stake)
}
#[cfg(not(any(test, feature = "mt")))]
{
let _ = (ctx, validator, stake);
let _ = (ctx, delegator, validator, stake);
Err(ContractError::Unauthorized)
}
}
Expand All @@ -159,17 +168,18 @@ impl ConverterContract<'_> {
fn test_unstake(
&self,
ctx: ExecCtx<custom::ConverterQuery>,
delegator: String,
validator: String,
unstake: Coin,
) -> Result<custom::Response, ContractError> {
#[cfg(any(test, feature = "mt"))]
{
// This can only ever be called in tests
self.unstake(ctx.deps, validator, unstake)
self.unstake(ctx.deps, delegator, validator, unstake)
}
#[cfg(not(any(test, feature = "mt")))]
{
let _ = (ctx, validator, unstake);
let _ = (ctx, delegator, validator, unstake);
Err(ContractError::Unauthorized)
}
}
Expand Down Expand Up @@ -214,6 +224,7 @@ impl ConverterContract<'_> {
pub(crate) fn stake(
&self,
deps: DepsMut<custom::ConverterQuery>,
delegator: String,
validator: String,
stake: Coin,
) -> Result<custom::Response, ContractError> {
Expand All @@ -223,7 +234,11 @@ impl ConverterContract<'_> {
.add_attribute("validator", &validator)
.add_attribute("amount", amount.amount.to_string());

let msg = virtual_staking_api::sv::ExecMsg::Bond { validator, amount };
let msg = virtual_staking_api::sv::ExecMsg::Bond {
delegator,
validator,
amount,
};
let msg = WasmMsg::Execute {
contract_addr: self.virtual_stake.load(deps.storage)?.into(),
msg: to_json_binary(&msg)?,
Expand All @@ -238,6 +253,7 @@ impl ConverterContract<'_> {
pub(crate) fn unstake(
&self,
deps: DepsMut<custom::ConverterQuery>,
delegator: String,
validator: String,
unstake: Coin,
) -> Result<custom::Response, ContractError> {
Expand All @@ -247,7 +263,11 @@ impl ConverterContract<'_> {
.add_attribute("validator", &validator)
.add_attribute("amount", amount.amount.to_string());

let msg = virtual_staking_api::sv::ExecMsg::Unbond { validator, amount };
let msg = virtual_staking_api::sv::ExecMsg::Unbond {
delegator,
validator,
amount,
};
let msg = WasmMsg::Execute {
contract_addr: self.virtual_stake.load(deps.storage)?.into(),
msg: to_json_binary(&msg)?,
Expand Down Expand Up @@ -603,4 +623,40 @@ impl ConverterApi for ConverterContract<'_> {
resp = resp.add_event(event);
Ok(resp)
}

fn internal_unstake(
&self,
ctx: ExecCtx<custom::ConverterQuery>,
delegator: String,
validator: String,
amount: Coin,
) -> Result<custom::Response, Self::Error> {
let virtual_stake = self.virtual_stake.load(ctx.deps.storage)?;
ensure_eq!(ctx.info.sender, virtual_stake, ContractError::Unauthorized);

#[allow(unused_mut)]
let mut resp = Response::new()
.add_attribute("action", "internal_unstake")
.add_attribute("amount", amount.amount.to_string())
.add_attribute("owner", delegator.clone());

let channel = IBC_CHANNEL.load(ctx.deps.storage)?;

// Recalculate the price when unbond
let inverted_amount = self.invert_price(ctx.deps.as_ref(), amount.clone())?;
let packet = ConsumerPacket::InternalUnstake {
delegator,
validator,
normalize_amount: amount,
inverted_amount,
};
let msg = IbcMsg::SendPacket {
channel_id: channel.endpoint.channel_id,
data: to_json_binary(&packet)?,
timeout: packet_timeout_internal_unstake(&ctx.env),
};
// send packet if we are ibc enabled
resp = resp.add_message(msg);
Ok(resp)
}
}
6 changes: 6 additions & 0 deletions contracts/consumer/converter/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ pub enum ContractError {
#[error("You must start the channel handshake on this side, it doesn't support OpenTry")]
IbcOpenTryDisallowed,

#[error("IBC channels not match")]
IbcChannelNotMatch,

#[error("You must start the channel close on provider side")]
IbcChannelCloseInitDisallowed,

#[error("Sent wrong denom over IBC: {sent}, expected {expected}")]
WrongDenom { sent: String, expected: String },

Expand Down
72 changes: 62 additions & 10 deletions contracts/consumer/converter/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cosmwasm_std::{
from_json, to_json_binary, DepsMut, Env, Event, Ibc3ChannelOpenResponse, IbcBasicResponse,
IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
IbcChannelOpenResponse, IbcMsg, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
IbcReceiveResponse, IbcTimeout, Validator,
IbcReceiveResponse, IbcTimeout, Validator, WasmMsg,
};
use cw_storage_plus::Item;

Expand All @@ -14,6 +14,7 @@ use mesh_apis::ibc::{
ack_success, validate_channel_order, AckWrapper, AddValidator, ConsumerPacket, ProtocolVersion,
ProviderPacket, StakeAck, TransferRewardsAck, UnstakeAck, PROTOCOL_NAME,
};
use mesh_apis::virtual_staking_api;
use sylvia::types::ExecCtx;

use crate::{
Expand All @@ -34,6 +35,8 @@ const DEFAULT_VALIDATOR_TIMEOUT: u64 = 24 * 60 * 60;
// But reward messages should go faster or timeout
const DEFAULT_REWARD_TIMEOUT: u64 = 60 * 60;

const DEFAULT_INTERNAL_UNSTAKE_TIMEOUT: u64 = 60 * 60;

pub fn packet_timeout_validator(env: &Env) -> IbcTimeout {
// No idea about their block time, but 24 hours ahead of our view of the clock
// should be decently in the future.
Expand All @@ -48,6 +51,16 @@ pub fn packet_timeout_rewards(env: &Env) -> IbcTimeout {
IbcTimeout::with_timestamp(timeout)
}

pub fn packet_timeout_internal_unstake(env: &Env) -> IbcTimeout {
// No idea about their block time, but 24 hours ahead of our view of the clock
// should be decently in the future.
let timeout = env
.block
.time
.plus_seconds(DEFAULT_INTERNAL_UNSTAKE_TIMEOUT);
IbcTimeout::with_timestamp(timeout)
}

#[cfg_attr(not(feature = "library"), entry_point)]
/// enforces ordering and versioning constraints
pub fn ibc_channel_open(
Expand Down Expand Up @@ -175,11 +188,18 @@ pub(crate) fn valset_update_msg(
/// On closed channel, we take all tokens from reflect contract to this contract.
/// We also delete the channel entry from accounts.
pub fn ibc_channel_close(
_deps: DepsMut,
deps: DepsMut,
_env: Env,
_msg: IbcChannelCloseMsg,
) -> Result<IbcBasicResponse, ContractError> {
todo!();
let contract = ConverterContract::new();
let msg = virtual_staking_api::sv::ExecMsg::HandleCloseChannel {};
let msg = WasmMsg::Execute {
contract_addr: contract.virtual_stake.load(deps.storage)?.into(),
msg: to_json_binary(&msg)?,
funds: vec![],
};
Ok(IbcBasicResponse::new().add_message(msg))
}

#[cfg_attr(not(feature = "library"), entry_point)]
Expand All @@ -195,11 +215,12 @@ pub fn ibc_packet_receive(
let contract = ConverterContract::new();
let res = match packet {
ProviderPacket::Stake {
delegator,
validator,
stake,
tx_id: _,
} => {
let response = contract.stake(deps, validator, stake)?;
let response = contract.stake(deps, delegator, validator, stake)?;
let ack = ack_success(&StakeAck {})?;
IbcReceiveResponse::new()
.set_ack(ack)
Expand All @@ -208,12 +229,13 @@ pub fn ibc_packet_receive(
.add_attributes(response.attributes)
}
ProviderPacket::Unstake {
delegator,
validator,
unstake,
tx_id: _,
} => {
let response = contract.unstake(deps, validator, unstake)?;
let ack = ack_success(&UnstakeAck {})?;
let response = contract.unstake(deps, delegator, validator, unstake)?;
let ack: cosmwasm_std::Binary = ack_success(&UnstakeAck {})?;
IbcReceiveResponse::new()
.set_ack(ack)
.add_submessages(response.messages)
Expand All @@ -232,9 +254,16 @@ pub fn ibc_packet_receive(
ProviderPacket::TransferRewards {
rewards, recipient, ..
} => {
let msg = contract.transfer_rewards(deps.as_ref(), recipient, rewards)?;
let msg =
contract.transfer_rewards(deps.as_ref(), recipient.clone(), rewards.clone())?;
let event = Event::new("mesh-transfer-rewards")
.add_attribute("recipient", &recipient)
.add_attribute("rewards", &rewards.amount.to_string());

Check failure on line 261 in contracts/consumer/converter/src/ibc.rs

View workflow job for this annotation

GitHub Actions / Lints

the borrowed expression implements the required traits
let ack = ack_success(&TransferRewardsAck {})?;
IbcReceiveResponse::new().set_ack(ack).add_message(msg)
IbcReceiveResponse::new()
.set_ack(ack)
.add_message(msg)
.add_event(event)
}
};
Ok(res)
Expand All @@ -245,14 +274,37 @@ pub fn ibc_packet_receive(
/// If it succeeded, take no action. If it errored, we can't do anything else and let it go.
/// We just log the error cases so they can be detected.
pub fn ibc_packet_ack(
_deps: DepsMut,
deps: DepsMut,
_env: Env,
msg: IbcPacketAckMsg,
) -> Result<IbcBasicResponse, ContractError> {
let ack: AckWrapper = from_json(&msg.acknowledgement.data)?;
let contract = ConverterContract::new();
let mut res = IbcBasicResponse::new();
match ack {
AckWrapper::Result(_) => {}
AckWrapper::Result(_) => {
let packet: ConsumerPacket = from_json(&msg.original_packet.data)?;
if let ConsumerPacket::InternalUnstake {
delegator,
validator,
normalize_amount,
inverted_amount: _,
} = packet
{
// execute virtual contract's internal unbond
let msg = virtual_staking_api::sv::ExecMsg::InternalUnbond {
delegator,
validator,
amount: normalize_amount,
};
let msg = WasmMsg::Execute {
contract_addr: contract.virtual_stake.load(deps.storage)?.into(),
msg: to_json_binary(&msg)?,
funds: vec![],
};
res = res.add_message(msg);
}
}
AckWrapper::Error(e) => {
// The wasmd framework will label this with the contract_addr, which helps us find the port and issue.
// Provide info to find the actual packet.
Expand Down
Loading

0 comments on commit 79bd951

Please sign in to comment.