Skip to content

Commit

Permalink
Merge pull request #78 from osmosis-labs/configure-max-slashable
Browse files Browse the repository at this point in the history
Configure max slashable
  • Loading branch information
ethanfrey authored Jun 28, 2023
2 parents 9f567ff + 1afae2a commit bdd9244
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 26 deletions.
22 changes: 12 additions & 10 deletions contracts/provider/external-staking/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl ExternalStakingContract<'_> {
Ok(id)
}

#[allow(clippy::too_many_arguments)]
#[msg(instantiate)]
pub fn instantiate(
&self,
Expand All @@ -89,15 +90,21 @@ impl ExternalStakingContract<'_> {
vault: String,
unbonding_period: u64,
remote_contact: crate::msg::AuthorizedEndpoint,
max_slashing: Decimal,
) -> Result<Response, ContractError> {
let vault = ctx.deps.api.addr_validate(&vault)?;
let vault = VaultApiHelper(vault);

if max_slashing > Decimal::one() {
return Err(ContractError::InvalidMaxSlashing);
}

let config = Config {
denom,
rewards_denom,
vault,
unbonding_period,
max_slashing,
};

self.config.save(ctx.deps.storage, &config)?;
Expand Down Expand Up @@ -899,16 +906,11 @@ pub mod cross_staking {
}

#[msg(query)]
fn max_slash(&self, _ctx: QueryCtx) -> Result<MaxSlashResponse, ContractError> {
// TODO: Properly set this value
// Arbitrary value - only to make some testing possible
//
// Probably should be queried from remote chain
let resp = MaxSlashResponse {
max_slash: Decimal::percent(5),
};

Ok(resp)
fn max_slash(&self, ctx: QueryCtx) -> Result<MaxSlashResponse, ContractError> {
let Config { max_slashing, .. } = self.config.load(ctx.deps.storage)?;
Ok(MaxSlashResponse {
max_slash: max_slashing,
})
}
}
}
3 changes: 3 additions & 0 deletions contracts/provider/external-staking/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub enum ContractError {
#[error("Invalid denom, {0} expected")]
InvalidDenom(String),

#[error("You cannot use a max slashing rate over 1.0 (100%)")]
InvalidMaxSlashing,

#[error("Not enough tokens staked, up to {0} can be unbond")]
NotEnoughStake(Uint128),

Expand Down
9 changes: 8 additions & 1 deletion contracts/provider/external-staking/src/multitest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ use crate::msg::{AuthorizedEndpoint, ReceiveVirtualStake, StakeInfo};
const OSMO: &str = "osmo";
const STAR: &str = "star";

/// 10% slashing on the remote chain
const SLASHING_PERCENTAGE: u64 = 10;
/// 5% slashing on the local chain (so we can differentiate in future tests)
const LOCAL_SLASHING_PERCENTAGE: u64 = 5;

// Shortcut setuping all needed contracts
//
// Returns vault and external staking proxies
Expand All @@ -37,6 +42,7 @@ fn setup<'app>(
let native_staking_instantiate = NativeStakingInstantiateMsg {
denom: OSMO.to_owned(),
proxy_code_id: native_staking_proxy_code.code_id(),
max_slashing: Decimal::percent(LOCAL_SLASHING_PERCENTAGE),
};

let staking_init = StakingInitInfo {
Expand All @@ -59,6 +65,7 @@ fn setup<'app>(
vault.contract_addr.to_string(),
unbond_period,
remote_contact,
Decimal::percent(SLASHING_PERCENTAGE),
)
.call(owner)?;

Expand All @@ -78,7 +85,7 @@ fn instantiate() {
assert_eq!(stakes.stakes, []);

let max_slash = contract.cross_staking_api_proxy().max_slash().unwrap();
assert_eq!(max_slash.max_slash, Decimal::percent(5));
assert_eq!(max_slash.max_slash, Decimal::percent(SLASHING_PERCENTAGE));
}

#[test]
Expand Down
6 changes: 4 additions & 2 deletions contracts/provider/external-staking/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{BlockInfo, Timestamp, Uint128, Uint256};
use cosmwasm_std::{BlockInfo, Decimal, Timestamp, Uint128, Uint256};
use mesh_apis::vault_api::VaultApiHelper;

use crate::points_alignment::PointsAlignment;
Expand All @@ -13,8 +13,10 @@ pub struct Config {
pub rewards_denom: String,
/// Vault contract address
pub vault: VaultApiHelper,
/// Ubbounding period for claims in seconds
/// Unbonding period for claims in seconds
pub unbonding_period: u64,
/// Max slash percentage (from InstantiateMsg, maybe later from the chain)
pub max_slashing: Decimal,
}

/// All single stake related information - entry per `(user, validator)` pair, including
Expand Down
1 change: 1 addition & 0 deletions contracts/provider/native-staking-proxy/src/multitest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fn setup<'app>(
msg: to_binary(&mesh_native_staking::contract::InstantiateMsg {
denom: OSMO.to_owned(),
proxy_code_id: staking_proxy_code.code_id(),
max_slashing: Decimal::percent(5),
})
.unwrap(),
label: None,
Expand Down
11 changes: 7 additions & 4 deletions contracts/provider/native-staking/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{from_slice, Addr, DepsMut, Reply, Response, SubMsgResponse};
use cosmwasm_std::{from_slice, Addr, Decimal, DepsMut, Reply, Response, SubMsgResponse};
use cw2::set_contract_version;
use cw_storage_plus::{Item, Map};
use cw_utils::parse_instantiate_response_data;
Expand All @@ -18,9 +18,6 @@ pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

pub const REPLY_ID_INSTANTIATE: u64 = 2;

// TODO: Hardcoded for now. Revisit for v1.
pub const MAX_SLASH_PERCENTAGE: u64 = 10;

pub struct NativeStakingContract<'a> {
pub config: Item<'a, Config>,
/// Map of proxy contract address by owner address
Expand Down Expand Up @@ -50,11 +47,17 @@ impl NativeStakingContract<'_> {
ctx: InstantiateCtx,
denom: String,
proxy_code_id: u64,
max_slashing: Decimal,
) -> Result<Response, ContractError> {
if max_slashing > Decimal::one() {
return Err(ContractError::InvalidMaxSlashing);
}

let config = Config {
denom,
proxy_code_id,
vault: ctx.info.sender,
max_slashing,
};
self.config.save(ctx.deps.storage, &config)?;
set_contract_version(ctx.deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
Expand Down
3 changes: 3 additions & 0 deletions contracts/provider/native-staking/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ pub enum ContractError {

#[error("Missing instantiate reply data")]
NoInstantiateData {},

#[error("You cannot use a max slashing rate over 1.0 (100%)")]
InvalidMaxSlashing,
}
11 changes: 6 additions & 5 deletions contracts/provider/native-staking/src/local_staking_api.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use cosmwasm_std::{ensure_eq, from_slice, to_binary, Binary, Decimal, Response, SubMsg, WasmMsg};
use cosmwasm_std::{ensure_eq, from_slice, to_binary, Binary, Response, SubMsg, WasmMsg};
use cw_utils::must_pay;
use sylvia::types::QueryCtx;
use sylvia::{contract, types::ExecCtx};

#[allow(unused_imports)]
use mesh_apis::local_staking_api::{self, LocalStakingApi, MaxSlashResponse};

use crate::contract::{NativeStakingContract, MAX_SLASH_PERCENTAGE, REPLY_ID_INSTANTIATE};
use crate::contract::{NativeStakingContract, REPLY_ID_INSTANTIATE};
use crate::error::ContractError;
use crate::msg::StakeMsg;

// FIXME: Move to sylvia contract macro
use crate::contract::BoundQuerier;
use crate::state::Config;

#[contract]
#[messages(local_staking_api as LocalStakingApi)]
Expand Down Expand Up @@ -77,11 +78,11 @@ impl LocalStakingApi for NativeStakingContract<'_> {
}

/// Returns the maximum percentage that can be slashed
/// TODO: Any way to query this from the chain? Or we just pass in InstantiateMsg?
#[msg(query)]
fn max_slash(&self, _ctx: QueryCtx) -> Result<MaxSlashResponse, Self::Error> {
fn max_slash(&self, ctx: QueryCtx) -> Result<MaxSlashResponse, Self::Error> {
let Config { max_slashing, .. } = self.config.load(ctx.deps.storage)?;
Ok(MaxSlashResponse {
max_slash: Decimal::percent(MAX_SLASH_PERCENTAGE),
max_slash: max_slashing,
})
}
}
21 changes: 18 additions & 3 deletions contracts/provider/native-staking/src/multitest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ use crate::msg::{OwnerByProxyResponse, ProxyByOwnerResponse};

const OSMO: &str = "OSMO";

const SLASHING_PERCENTAGE: u64 = 15;

fn slashing_rate() -> Decimal {
Decimal::percent(SLASHING_PERCENTAGE)
}

#[test]
fn instantiation() {
let app = App::default();
Expand All @@ -25,7 +31,11 @@ fn instantiation() {
let staking_code = contract::multitest_utils::CodeId::store_code(&app);

let staking = staking_code
.instantiate(OSMO.to_owned(), staking_proxy_code.code_id())
.instantiate(
OSMO.to_owned(),
staking_proxy_code.code_id(),
slashing_rate(),
)
.with_label("Staking")
.call(owner)
.unwrap();
Expand All @@ -34,7 +44,7 @@ fn instantiation() {
assert_eq!(config.denom, OSMO);

let res = staking.local_staking_api_proxy().max_slash().unwrap();
assert_eq!(res.max_slash, Decimal::percent(10));
assert_eq!(res.max_slash, slashing_rate());
}

#[test]
Expand All @@ -60,7 +70,11 @@ fn receiving_stake() {
let staking_code = contract::multitest_utils::CodeId::store_code(&app);

let staking = staking_code
.instantiate(OSMO.to_owned(), staking_proxy_code.code_id())
.instantiate(
OSMO.to_owned(),
staking_proxy_code.code_id(),
slashing_rate(),
)
.with_label("Staking")
.call(owner)
.unwrap();
Expand Down Expand Up @@ -196,6 +210,7 @@ fn releasing_proxy_stake() {
msg: to_binary(&crate::contract::InstantiateMsg {
denom: OSMO.to_owned(),
proxy_code_id: staking_proxy_code.code_id(),
max_slashing: slashing_rate(),
})
.unwrap(),
label: None,
Expand Down
5 changes: 4 additions & 1 deletion contracts/provider/native-staking/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Addr;
use cosmwasm_std::{Addr, Decimal};

#[cw_serde]
pub struct Config {
Expand All @@ -11,4 +11,7 @@ pub struct Config {

/// The address of the vault contract (where we get and return stake)
pub vault: Addr,

/// Max slash percentage (from InstantiateMsg, maybe later from the chain)
pub max_slashing: Decimal,
}

0 comments on commit bdd9244

Please sign in to comment.