Skip to content

Commit

Permalink
Send IBC packets on stake/unstake
Browse files Browse the repository at this point in the history
  • Loading branch information
ethanfrey committed Jun 23, 2023
1 parent 426c594 commit 34c0f99
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 12 deletions.
64 changes: 53 additions & 11 deletions contracts/provider/external-staking/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ use mesh_apis::local_staking_api::MaxSlashResponse;
use mesh_apis::vault_api::VaultApiHelper;
use mesh_sync::Lockable;

// IBC sending is disabled in tests...
#[cfg(not(test))]
use crate::ibc::{packet_timeout, IBC_CHANNEL};
#[cfg(not(test))]
use cosmwasm_std::{to_binary, IbcMsg};
#[cfg(not(test))]
use mesh_apis::ibc::ProviderPacket;

use sylvia::contract;
use sylvia::types::{ExecCtx, InstantiateCtx, QueryCtx};

Expand Down Expand Up @@ -264,17 +272,34 @@ impl ExternalStakingContract<'_> {
id: tx_id,
amount: amount.amount,
user: ctx.info.sender.clone(),
validator,
validator: validator.clone(),
};
self.pending_txs.save(ctx.deps.storage, tx_id, &new_tx)?;

// TODO: Remote IBC should happen here.
// Or maybe `unstake` should be called via IBC. To be specified
let resp = Response::new()
let mut resp = Response::new()
.add_attribute("action", "unstake")
.add_attribute("owner", ctx.info.sender.into_string())
.add_attribute("amount", amount.amount.to_string());

// add ibc packet if we are ibc enabled (skip in tests)
#[cfg(not(test))]
{
let channel = IBC_CHANNEL.load(ctx.deps.storage)?;
let packet = ProviderPacket::Unstake {
validator,
unstake: amount,
tx_id,
};
let msg = IbcMsg::SendPacket {
channel_id: channel.endpoint.channel_id,
data: to_binary(&packet)?,
timeout: packet_timeout(&ctx.env),
};
resp = resp.add_message(msg);
}

// put this later so compiler doens't complain about mut in test mode
resp = resp.add_attribute("owner", ctx.info.sender);

Ok(resp)
}

Expand Down Expand Up @@ -763,22 +788,39 @@ pub mod cross_staking {
self.stakes
.save(ctx.deps.storage, (&owner, &msg.validator), &stake_lock)?;

// TODO: Send proper IBC message to remote staking contract

// Save tx
let new_tx = Tx::InFlightRemoteStaking {
id: tx_id,
amount: amount.amount,
user: owner.clone(),
validator: msg.validator,
validator: msg.validator.clone(),
};
self.pending_txs.save(ctx.deps.storage, tx_id, &new_tx)?;

let resp = Response::new()
let mut resp = Response::new()
.add_attribute("action", "receive_virtual_stake")
.add_attribute("owner", owner)
.add_attribute("amount", amount.amount.to_string())
.add_attribute("tx_id", tx_id.to_string());
.add_attribute("amount", amount.amount.to_string());

// add ibc packet if we are ibc enabled (skip in tests)
#[cfg(not(test))]
{
let channel = IBC_CHANNEL.load(ctx.deps.storage)?;
let packet = ProviderPacket::Stake {
validator: msg.validator,
stake: amount,
tx_id,
};
let msg = IbcMsg::SendPacket {
channel_id: channel.endpoint.channel_id,
data: to_binary(&packet)?,
timeout: packet_timeout(&ctx.env),
};
resp = resp.add_message(msg);
}

// This is later so `mut resp` is valid in test and non-test code
resp = resp.add_attribute("tx_id", tx_id.to_string());

Ok(resp)
}
Expand Down
13 changes: 12 additions & 1 deletion contracts/provider/external-staking/src/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cosmwasm_std::entry_point;
use cosmwasm_std::{
from_slice, DepsMut, Env, Ibc3ChannelOpenResponse, IbcBasicResponse, IbcChannel,
IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg, IbcChannelOpenResponse,
IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse,
IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg, IbcReceiveResponse, IbcTimeout,
};
use cw_storage_plus::Item;
use mesh_apis::ibc::{
Expand All @@ -31,6 +31,17 @@ pub const IBC_CHANNEL: Item<IbcChannel> = Item::new("ibc_channel");

pub const VAL_CRDT: CrdtState = CrdtState::new();

// If we don't hear anything within 10 minutes, let's abort, for better UX
// This is long enough to allow some clock drift between chains
const DEFAULT_TIMEOUT: u64 = 10 * 60;

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

#[cfg_attr(not(feature = "library"), entry_point)]
/// enforces ordering and versioning constraints
pub fn ibc_channel_open(
Expand Down

0 comments on commit 34c0f99

Please sign in to comment.