Skip to content

Commit

Permalink
Merge pull request #53 from hadronlabs-org/feat/lsm-fixes
Browse files Browse the repository at this point in the history
feat: lsm fixes
  • Loading branch information
oldremez authored Mar 26, 2024
2 parents ecbbc0a + 83a6eaf commit ba218e4
Show file tree
Hide file tree
Showing 37 changed files with 501 additions and 656 deletions.
44 changes: 37 additions & 7 deletions contracts/core/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use drop_puppeteer_base::state::RedeemShareItem;
use drop_staking_base::state::core::{
unbond_batches_map, Config, ConfigOptional, ContractState, FeeItem, NonNativeRewardsItem,
UnbondBatch, UnbondBatchStatus, UnbondItem, BONDED_AMOUNT, COLLECTED_FEES, CONFIG,
EXCHANGE_RATE, FAILED_BATCH_ID, FSM, LAST_ICA_BALANCE_CHANGE_HEIGHT, LAST_PUPPETEER_RESPONSE,
LSM_SHARES_TO_REDEEM, NON_NATIVE_REWARDS_CONFIG, PENDING_LSM_SHARES, PENDING_TRANSFER,
PRE_UNBONDING_BALANCE, TOTAL_LSM_SHARES, UNBOND_BATCH_ID,
EXCHANGE_RATE, FAILED_BATCH_ID, FSM, LAST_ICA_BALANCE_CHANGE_HEIGHT, LAST_LSM_REDEEM,
LAST_PUPPETEER_RESPONSE, LSM_SHARES_TO_REDEEM, NON_NATIVE_REWARDS_CONFIG, PENDING_LSM_SHARES,
PENDING_TRANSFER, PRE_UNBONDING_BALANCE, TOTAL_LSM_SHARES, UNBOND_BATCH_ID,
};
use drop_staking_base::state::validatorset::ValidatorInfo;
use drop_staking_base::state::withdrawal_voucher::{Metadata, Trait};
Expand Down Expand Up @@ -60,6 +60,7 @@ pub fn instantiate(
LAST_ICA_BALANCE_CHANGE_HEIGHT.save(deps.storage, &0)?;
TOTAL_LSM_SHARES.save(deps.storage, &0)?;
BONDED_AMOUNT.save(deps.storage, &Uint128::zero())?;
LAST_LSM_REDEEM.save(deps.storage, &0)?;
Ok(response("instantiate", CONTRACT_NAME, attrs))
}

Expand Down Expand Up @@ -345,6 +346,7 @@ fn execute_puppeteer_hook(
LSM_SHARES_TO_REDEEM.remove(deps.storage, item.local_denom.to_string());
}
TOTAL_LSM_SHARES.update(deps.storage, |one| StdResult::Ok(one - sum))?;
LAST_LSM_REDEEM.save(deps.storage, &env.block.time.seconds())?;
}
_ => {}
}
Expand Down Expand Up @@ -416,7 +418,7 @@ fn execute_tick_idle(
{
messages.push(lsm_msg);
} else if let Some(lsm_msg) =
get_pending_lsm_share_msg(deps, config, &env, info.funds.clone())?
get_pending_lsm_share_msg(deps.branch(), config, &env, info.funds.clone())?
{
messages.push(lsm_msg);
} else {
Expand Down Expand Up @@ -764,6 +766,12 @@ fn execute_bond(
let denom_type = check_denom::check_denom(&deps, &denom, &config)?;

if let check_denom::DenomType::LsmShare(remote_denom) = denom_type {
if amount < config.lsm_min_bond_amount {
return Err(ContractError::LSMBondAmountIsBelowMinimum {
min_stake_amount: config.lsm_min_bond_amount,
bond_amount: amount,
});
}
TOTAL_LSM_SHARES.update(deps.storage, |total| StdResult::Ok(total + amount.u128()))?;
PENDING_LSM_SHARES.update(deps.storage, denom, |one| {
let mut new = one.unwrap_or((remote_denom, Uint128::zero()));
Expand Down Expand Up @@ -876,6 +884,24 @@ fn execute_update_config(
));
config.unbond_batch_switch_time = unbond_batch_switch_time;
}
if let Some(lsm_min_bond_amount) = new_config.lsm_min_bond_amount {
attrs.push(attr("lsm_min_bond_amount", lsm_min_bond_amount.to_string()));
config.lsm_min_bond_amount = lsm_min_bond_amount;
}
if let Some(lsm_redeem_maximum_interval) = new_config.lsm_redeem_maximum_interval {
attrs.push(attr(
"lsm_redeem_maximum_interval",
lsm_redeem_maximum_interval.to_string(),
));
config.lsm_redeem_maximum_interval = lsm_redeem_maximum_interval;
}
if let Some(lsm_redeem_threshold) = new_config.lsm_redeem_threshold {
attrs.push(attr(
"lsm_redeem_threshold",
lsm_redeem_threshold.to_string(),
));
config.lsm_redeem_threshold = lsm_redeem_threshold;
}
if let Some(bond_limit) = new_config.bond_limit {
attrs.push(attr("bond_limit", bond_limit.to_string()));
config.bond_limit = {
Expand Down Expand Up @@ -1308,10 +1334,14 @@ fn get_pending_redeem_msg<T>(
env: &Env,
funds: Vec<cosmwasm_std::Coin>,
) -> ContractResult<Option<CosmosMsg<T>>> {
if LSM_SHARES_TO_REDEEM
let pending_lsm_shares_count = LSM_SHARES_TO_REDEEM
.keys(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.count()
< config.lsm_redeem_threshold as usize
.count();
let last_lsm_redeem = LAST_LSM_REDEEM.load(deps.storage)?;
let lsm_redeem_threshold = config.lsm_redeem_threshold as usize;
if pending_lsm_shares_count == 0
|| ((pending_lsm_shares_count < lsm_redeem_threshold)
|| (last_lsm_redeem + config.lsm_redeem_maximum_interval > env.block.time.seconds()))
{
return Ok(None);
}
Expand Down
8 changes: 7 additions & 1 deletion contracts/core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{OverflowError, StdError};
use cosmwasm_std::{OverflowError, StdError, Uint128};
use cw_ownable::OwnershipError;
use drop_helpers::pause::PauseError;
use neutron_sdk::NeutronError;
Expand Down Expand Up @@ -60,6 +60,12 @@ pub enum ContractError {
#[error("ICA balance is zero")]
ICABalanceZero {},

#[error("Bond amount is less than minimum LSM bond amount: {min_stake_amount}. Provided: {bond_amount}")]
LSMBondAmountIsBelowMinimum {
min_stake_amount: Uint128,
bond_amount: Uint128,
},

#[error("Puppeteer response is not received")]
PuppeteerResponseIsNotReceived {},

Expand Down
2 changes: 2 additions & 0 deletions contracts/core/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ fn get_default_config(fee: Option<Decimal>) -> Config {
fee,
fee_address: Some("fee_address".to_string()),
lsm_redeem_threshold: 10u64,
lsm_min_bond_amount: Uint128::one(),
lsm_redeem_maximum_interval: 10_000_000_000,
bond_limit: None,
emergency_address: None,
min_stake_amount: Uint128::new(100),
Expand Down
2 changes: 2 additions & 0 deletions contracts/factory/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,9 @@ fn execute_init(
idle_min_interval: core_params.idle_min_interval,
bond_limit: core_params.bond_limit,
channel: core_params.channel,
lsm_min_bond_amount: core_params.lsm_min_bond_amount,
lsm_redeem_threshold: core_params.lsm_redeem_threshold,
lsm_redeem_max_interval: core_params.lsm_redeem_max_interval,
owner: env.contract.address.to_string(),
fee: None,
fee_address: None,
Expand Down
2 changes: 2 additions & 0 deletions contracts/factory/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ pub struct CoreParams {
pub unbonding_period: u64,
pub unbonding_safe_period: u64,
pub unbond_batch_switch_time: u64,
pub lsm_min_bond_amount: Uint128,
pub lsm_redeem_threshold: u64,
pub lsm_redeem_max_interval: u64, //seconds
pub channel: String,
pub bond_limit: Option<Uint128>,
pub min_stake_amount: Uint128,
Expand Down
4 changes: 2 additions & 2 deletions integration_tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"test:poc-provider-proposals": "vitest --run poc-provider-proposals.test.ts --bail 1",
"test:poc-proposal-votes": "vitest --run poc-proposal-votes.test.ts --bail 1",
"test:core": "vitest --run core.test.ts --bail 1",
"test:core:slashing": "vitest --run core.slashing.test.ts --bail 1",
"test:core:slashing": "vitest --run core-slashing.test.ts --bail 1",
"test:pump": "vitest --run pump.test.ts --bail 1",
"test:pump-multi": "vitest --run pump-multi.test.ts --bail 1",
"test:puppeteer": "vitest --run puppeteer.test.ts --bail 1",
Expand Down Expand Up @@ -37,7 +37,7 @@
"@cosmjs/stargate": "^0.32.1",
"@cosmjs/tendermint-rpc": "^0.32.1",
"@neutron-org/client-ts": "^1.4.0",
"@neutron-org/contracts2ts": "^1.3.8",
"@neutron-org/contracts2ts": "^1.4.0",
"@neutron-org/cosmopark": "^1.5.0",
"bech32": "^1.1.4"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,6 @@ import { Coin } from "@cosmjs/amino";
* let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```
*/
export type Uint128 = string;

export interface InstantiateMsg {
core_contract: string;
cron_address: string;
from_denom: string;
min_rewards: Uint128;
owner: string;
pair_contract: string;
router_contract: string;
}
/**
* A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.
*
* # Examples
*
* Use `from` to create instances of this and `u128` to get the value out:
*
* ``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);
*
* let b = Uint128::from(42u64); assert_eq!(b.u128(), 42);
*
* let c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```
*/
export type Uint128 = string;
/**
* This enum describes a swap operation.
*/
Expand Down Expand Up @@ -95,6 +71,7 @@ export type Addr = string;
export interface DropAstroportExchangeHandlerSchema {
responses: ConfigResponse;
execute: UpdateConfigArgs | UpdateSwapOperationsArgs;
instantiate?: InstantiateMsg;
[k: string]: unknown;
}
export interface ConfigResponse {
Expand All @@ -119,6 +96,15 @@ export interface UpdateConfigArgs {
export interface UpdateSwapOperationsArgs {
operations?: SwapOperation[] | null;
}
export interface InstantiateMsg {
core_contract: string;
cron_address: string;
from_denom: string;
min_rewards: Uint128;
owner: string;
pair_contract: string;
router_contract: string;
}


function isSigningCosmWasmClient(
Expand All @@ -143,8 +129,8 @@ export class Client {
codeId: number,
initMsg: InstantiateMsg,
label: string,
fees: StdFee | 'auto' | number,
initCoins?: readonly Coin[],
fees?: StdFee | 'auto' | number,
): Promise<InstantiateResult> {
const res = await client.instantiate(sender, codeId, initMsg, label, fees, {
...(initCoins && initCoins.length && { funds: initCoins }),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult, InstantiateResult } from "@cosmjs/cosmwasm-stargate";
import { StdFee } from "@cosmjs/amino";
export interface InstantiateMsg {
core_address: string;
ld_token: string;
withdrawal_manager_address: string;
withdrawal_voucher_address: string;
}
/**
* A thin wrapper around u128 that is using strings for JSON encoding/decoding, such that the full u128 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.
*
Expand Down Expand Up @@ -34,6 +28,7 @@ export interface DropAutoWithdrawerSchema {
responses: BondingsResponse | InstantiateMsg;
query: BondingsArgs;
execute: BondArgs | UnbondArgs | WithdrawArgs;
instantiate?: InstantiateMsg1;
[k: string]: unknown;
}
export interface BondingsResponse {
Expand Down Expand Up @@ -76,6 +71,12 @@ export interface UnbondArgs {
export interface WithdrawArgs {
token_id: string;
}
export interface InstantiateMsg1 {
core_address: string;
ld_token: string;
withdrawal_manager_address: string;
withdrawal_voucher_address: string;
}


function isSigningCosmWasmClient(
Expand All @@ -100,8 +101,8 @@ export class Client {
codeId: number,
initMsg: InstantiateMsg,
label: string,
fees: StdFee | 'auto' | number,
initCoins?: readonly Coin[],
fees?: StdFee | 'auto' | number,
): Promise<InstantiateResult> {
const res = await client.instantiate(sender, codeId, initMsg, label, fees, {
...(initCoins && initCoins.length && { funds: initCoins }),
Expand Down
Loading

0 comments on commit ba218e4

Please sign in to comment.