use crate::contract::{execute, instantiate, query};
use crate::testing::mock_querier::mock_dependencies;
use cosmwasm_std::testing::{mock_env, mock_info};
use cosmwasm_std::{
attr, from_json, to_json_binary, CosmosMsg, Decimal256, StdError, SubMsg, Uint128, Uint256,
WasmMsg,
};
use cw20::{Cw20ExecuteMsg, Cw20ReceiveMsg};
use solid_moneymarket::liquidation::MarketExecuteMsg;
use solid_moneymarket::liquidation_queue::{
BidResponse, CollateralInfoResponse, ConfigResponse, Cw20HookMsg, ExecuteMsg, InstantiateMsg,
QueryMsg,
};
#[test]
fn proper_initialization() {
let mut deps = mock_dependencies(&[]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(0, res.messages.len());
let value: ConfigResponse = from_json(&query(deps.as_ref(), mock_env(), QueryMsg::Config {}).unwrap()).unwrap();
assert_eq!(
value,
ConfigResponse {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
}
);
}
#[test]
fn update_config() {
let mut deps = mock_dependencies(&[]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("owner0000", &[]);
let msg = ExecuteMsg::UpdateConfig {
owner: Some("owner0001".to_string()),
oracle_contract: None,
safe_ratio: None,
bid_fee: Some(Decimal256::one()),
liquidator_fee: None,
liquidation_threshold: None,
price_timeframe: None,
waiting_period: None,
overseer: None,
};
let err = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap_err();
assert_eq!(
err,
StdError::generic_err("The sum of bid_fee and liquidator_fee can not be greater than one")
);
let msg = ExecuteMsg::UpdateConfig {
owner: Some("owner0001".to_string()),
oracle_contract: None,
safe_ratio: None,
bid_fee: None,
liquidator_fee: None,
liquidation_threshold: None,
price_timeframe: None,
waiting_period: None,
overseer: None,
};
let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(0, res.messages.len());
let value: ConfigResponse = from_json(&query(deps.as_ref(), mock_env(), QueryMsg::Config {}).unwrap()).unwrap();
assert_eq!(
value,
ConfigResponse {
owner: "owner0001".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
}
);
let info = mock_info("owner0001", &[]);
let msg = ExecuteMsg::UpdateConfig {
owner: None,
oracle_contract: Some("oracle0001".to_string()),
safe_ratio: Some(Decimal256::percent(15)),
bid_fee: Some(Decimal256::percent(2)),
liquidator_fee: Some(Decimal256::percent(1)),
liquidation_threshold: Some(Uint256::from(150000000u64)),
price_timeframe: Some(120u64),
waiting_period: Some(100u64),
overseer: Some("overseer0001".to_string()),
};
let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(0, res.messages.len());
let value: ConfigResponse = from_json(&query(deps.as_ref(), mock_env(), QueryMsg::Config {}).unwrap()).unwrap();
assert_eq!(
value,
ConfigResponse {
owner: "owner0001".to_string(),
oracle_contract: "oracle0001".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(15),
bid_fee: Decimal256::percent(2),
liquidator_fee: Decimal256::percent(1),
liquidation_threshold: Uint256::from(150000000u64),
price_timeframe: 120u64,
waiting_period: 100u64,
overseer: "overseer0001".to_string(),
}
);
let info = mock_info("owner0000", &[]);
let msg = ExecuteMsg::UpdateConfig {
owner: None,
oracle_contract: Some("oracle0001".to_string()),
safe_ratio: Some(Decimal256::percent(1)),
bid_fee: Some(Decimal256::percent(2)),
liquidator_fee: Some(Decimal256::percent(1)),
liquidation_threshold: Some(Uint256::from(150000000u64)),
price_timeframe: Some(100u64),
waiting_period: Some(100u64),
overseer: Some("overseer0001".to_string()),
};
let err = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err();
assert_eq!(err, StdError::generic_err("unauthorized"));
}
#[test]
fn submit_bid() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("stable0001", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(0u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let err = execute(deps.as_mut(), mock_env(), info, msg).unwrap_err();
assert_eq!(
err,
StdError::generic_err("unauthorized stable have been provided")
);
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let bid_response: BidResponse = from_json(
&query(
deps.as_ref(),
mock_env(),
QueryMsg::Bid {
bid_idx: Uint128::from(1u128),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(
bid_response,
BidResponse {
idx: Uint128::from(1u128),
collateral_token: "asset0000".to_string(),
bidder: "addr0000".to_string(),
amount: Uint256::from(1000000u128),
premium_slot: 1u8,
product_snapshot: Decimal256::one(),
sum_snapshot: Decimal256::zero(),
pending_liquidated_collateral: Uint256::zero(),
wait_end: Some(wait_end.seconds()),
epoch_snapshot: Uint128::zero(),
scale_snapshot: Uint128::zero(),
}
);
}
#[test]
fn activate_bid() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: Some(vec![Uint128::from(1u64)]),
};
let info = mock_info("addr0001", &[]);
let mut env = mock_env();
env.block.time = wait_end;
let err = execute(deps.as_mut(), env, info, msg.clone()).unwrap_err();
assert_eq!(err, StdError::generic_err("unauthorized"));
let info = mock_info("addr0000", &[]);
let mut env = mock_env();
env.block.time = wait_end.minus_seconds(2u64);
let err = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone()).unwrap_err();
assert_eq!(
err,
StdError::generic_err(format!("Wait period expires at {}", wait_end.seconds()))
);
let msg2 = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: None,
};
let res = execute(deps.as_mut(), env, info, msg2).unwrap();
assert_eq!(
res.attributes,
vec![attr("action", "activate_bids"), attr("amount", "0"),]
);
let info = mock_info("addr0000", &[]);
let mut env = mock_env();
env.block.time = wait_end;
let res = execute(deps.as_mut(), env, info, msg).unwrap();
assert_eq!(
res.attributes,
vec![attr("action", "activate_bids"), attr("amount", "1000000"),]
);
assert!(res.messages.is_empty());
let bid_response: BidResponse = from_json(
&query(
deps.as_ref(),
mock_env(),
QueryMsg::Bid {
bid_idx: Uint128::from(1u128),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(
bid_response,
BidResponse {
idx: Uint128::from(1u128),
collateral_token: "asset0000".to_string(),
bidder: "addr0000".to_string(),
amount: Uint256::from(1000000u128),
premium_slot: 1u8,
product_snapshot: Decimal256::from_ratio(Decimal256::one().atomics(), Uint256::one()),
sum_snapshot: Decimal256::zero(),
pending_liquidated_collateral: Uint256::zero(),
wait_end: None,
epoch_snapshot: Uint128::zero(),
scale_snapshot: Uint128::zero(),
}
);
}
#[test]
fn retract_bid() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: Some(vec![Uint128::from(1u64)]),
};
let mut env = mock_env();
env.block.time = wait_end;
let info = mock_info("addr0000", &[]);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::RetractBid {
bid_idx: Uint128::from(1u128),
amount: None,
};
let info = mock_info("addr0000", &[]);
let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(
res.messages,
vec![SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: "stable0000".to_string(),
funds: vec![],
msg: to_json_binary(&Cw20ExecuteMsg::Transfer {
recipient: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
})
.unwrap(),
}))]
);
}
#[test]
fn retract_unactive_bid() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::RetractBid {
bid_idx: Uint128::from(1u128),
amount: Some(Uint256::from(500000u128)),
};
let info = mock_info("addr0000", &[]);
let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(
res.attributes,
vec![
attr("action", "retract_bid"),
attr("bid_idx", "1"),
attr("amount", "500000"),
]
);
let msg = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: None,
};
let info = mock_info("addr0000", &[]);
let mut env = mock_env();
env.block.time = wait_end;
let res = execute(deps.as_mut(), env, info, msg).unwrap();
assert_eq!(
res.attributes,
vec![attr("action", "activate_bids"), attr("amount", "500000"),]
);
}
#[test]
fn execute_bid() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(1),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 100000u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let env = mock_env();
deps.querier.with_oracle_price(&[(
&("asset0000".to_string(), "uusd".to_string()),
&(
Decimal256::percent(50),
env.block.time.seconds(),
env.block.time.seconds(),
),
)]);
let _res = instantiate(deps.as_mut(), env.clone(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), env, info, msg).unwrap();
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: Some(vec![Uint128::from(1u128)]),
};
let mut env = mock_env();
env.block.time = wait_end;
let info = mock_info("addr0000", &[]);
execute(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0001".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::ExecuteBid {
liquidator: "liquidator00000".to_string(),
fee_address: Some("fee0000".to_string()),
repay_address: Some("repay0000".to_string()),
borrower_address: Some("addr0000".to_string()),
})
.unwrap(),
});
let info = mock_info("asset0000", &[]);
let env = mock_env();
let err = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap_err();
assert_eq!(
err,
StdError::generic_err("Unauthorized: only custody contract can execute liquidations",)
);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "custody0000".to_string(), amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::ExecuteBid {
liquidator: "liquidator0000".to_string(),
fee_address: Some("fee0000".to_string()),
repay_address: Some("repay0000".to_string()),
borrower_address: Some("addr0000".to_string()),
})
.unwrap(),
});
let res = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap();
assert_eq!(
res.messages,
vec![
SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: "stable0000".to_string(),
funds: vec![],
msg: to_json_binary(&Cw20ExecuteMsg::Send {
contract: "repay0000".to_string(),
amount: Uint128::from(485100u128),
msg: to_json_binary(&MarketExecuteMsg::RepayStableFromLiquidation {
borrower: "addr0000".to_string()
})
.unwrap(),
})
.unwrap(),
})),
SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: "stable0000".to_string(),
funds: vec![],
msg: to_json_binary(&Cw20ExecuteMsg::Transfer {
recipient: "fee0000".to_string(),
amount: Uint128::from(4950u128),
})
.unwrap(),
})),
SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: "stable0000".to_string(),
funds: vec![],
msg: to_json_binary(&Cw20ExecuteMsg::Transfer {
recipient: "liquidator0000".to_string(),
amount: Uint128::from(4950u128),
})
.unwrap(),
})),
]
);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "custody0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::ExecuteBid {
liquidator: "liquidator0000".to_string(),
fee_address: None,
repay_address: None,
borrower_address: Some("addr0000".to_string()),
})
.unwrap(),
});
let res = execute(deps.as_mut(), env.clone(), info.clone(), msg).unwrap_err();
assert_eq!(
res,
StdError::generic_err("Invalid message, specifiy all the field")
);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "custody0000".to_string(),
amount: Uint128::from(2020206u128),
msg: to_json_binary(&Cw20HookMsg::ExecuteBid {
liquidator: "liquidator00000".to_string(),
fee_address: Some("fee0000".to_string()),
repay_address: Some("repay0000".to_string()),
borrower_address: Some("addr0000".to_string()),
})
.unwrap(),
});
let res = execute(deps.as_mut(), env, info, msg).unwrap_err();
assert_eq!(
res,
StdError::generic_err("Not enough bids to execute this liquidation")
);
}
#[test]
fn claim_liquidations() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"asset0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 1000000u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let env = mock_env();
deps.querier.with_oracle_price(&[(
&("asset0000".to_string(), "uusd".to_string()),
&(
Decimal256::percent(50),
env.block.time.seconds(),
env.block.time.seconds(),
),
)]);
let _res = instantiate(deps.as_mut(), env, info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "asset0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::zero(),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let info = mock_info("stable0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "addr0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::SubmitBid {
collateral_token: "asset0000".to_string(),
premium_slot: 1u8,
})
.unwrap(),
});
let env = mock_env();
let wait_end = env.block.time.plus_seconds(60u64);
execute(deps.as_mut(), env, info, msg).unwrap();
let info = mock_info("addr0000", &[]);
let msg = ExecuteMsg::ActivateBids {
collateral_token: "asset0000".to_string(),
bids_idx: Some(vec![Uint128::from(1u128)]),
};
let mut env = mock_env();
env.block.time = wait_end;
execute(deps.as_mut(), env, info, msg).unwrap();
let info = mock_info("asset0000", &[]);
let msg = ExecuteMsg::Receive(Cw20ReceiveMsg {
sender: "custody0000".to_string(),
amount: Uint128::from(1000000u128),
msg: to_json_binary(&Cw20HookMsg::ExecuteBid {
liquidator: "liquidator00000".to_string(),
fee_address: Some("fee0000".to_string()),
repay_address: Some("repay0000".to_string()),
borrower_address: Some("addr0000".to_string()),
})
.unwrap(),
});
let _res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::ClaimLiquidations {
collateral_token: "asset0000".to_string(),
bids_idx: None,
};
let info = mock_info("addr0000", &[]);
let res = execute(deps.as_mut(), mock_env(), info, msg).unwrap();
assert_eq!(
res.attributes,
vec![
attr("action", "claim_liquidations"),
attr("collateral_token", "asset0000"),
attr("collateral_amount", "1000000"),
]
);
}
#[test]
fn update_collateral_info() {
let mut deps = mock_dependencies(&[]);
deps.querier
.with_collateral_max_ltv(&[(&"token0000".to_string(), &Decimal256::percent(90))]);
let msg = InstantiateMsg {
owner: "owner0000".to_string(),
oracle_contract: "oracle0000".to_string(),
stable_contract: "stable0000".to_string(),
safe_ratio: Decimal256::percent(10),
bid_fee: Decimal256::percent(1),
liquidator_fee: Decimal256::percent(0),
liquidation_threshold: Uint256::from(100000000u64),
price_timeframe: 60u64,
waiting_period: 60u64,
overseer: "overseer0000".to_string(),
};
let info = mock_info("addr0000", &[]);
let _res = instantiate(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::WhitelistCollateral {
collateral_token: "token0000".to_string(),
max_slot: 30u8,
bid_threshold: Uint256::from(10000u128),
premium_rate_per_slot: Decimal256::percent(1),
};
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let msg = ExecuteMsg::UpdateCollateralInfo {
collateral_token: "token0000".to_string(),
bid_threshold: Some(Uint256::from(20000u128)),
max_slot: Some(20u8),
};
let info = mock_info("addr0000", &[]);
let err = execute(deps.as_mut(), mock_env(), info, msg.clone()).unwrap_err();
assert_eq!(err, StdError::generic_err("unauthorized"));
let info = mock_info("owner0000", &[]);
execute(deps.as_mut(), mock_env(), info, msg).unwrap();
let collateral_info_response: CollateralInfoResponse = from_json(
&query(
deps.as_ref(),
mock_env(),
QueryMsg::CollateralInfo {
collateral_token: "token0000".to_string(),
},
)
.unwrap(),
)
.unwrap();
assert_eq!(
collateral_info_response,
CollateralInfoResponse {
collateral_token: "token0000".to_string(),
max_slot: 20u8, bid_threshold: Uint256::from(20000u128), premium_rate_per_slot: Decimal256::percent(1),
}
);
}