Skip to content

Commit

Permalink
Add denoms with interface contract
Browse files Browse the repository at this point in the history
  • Loading branch information
lubkoll committed Jul 19, 2024
1 parent b87d7bc commit c824eb8
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 5 deletions.
64 changes: 64 additions & 0 deletions smart-contracts/contracts/babylon-vault/schema/babylon-vault.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,31 @@
],
"properties": {
"register_lst": {
"type": "object",
"required": [
"denom",
"interface"
],
"properties": {
"denom": {
"type": "string"
},
"interface": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"unregister_lst"
],
"properties": {
"unregister_lst": {
"type": "object",
"required": [
"denom"
Expand Down Expand Up @@ -214,6 +239,19 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"lsts"
],
"properties": {
"lsts": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
]
},
Expand All @@ -232,6 +270,32 @@
"description": "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.\n\n# Examples\n\nUse `from` to create instances of this and `u128` to get the value out:\n\n``` # use cosmwasm_std::Uint128; let a = Uint128::from(123u128); assert_eq!(a.u128(), 123);\n\nlet b = Uint128::from(42u64); assert_eq!(b.u128(), 42);\n\nlet c = Uint128::from(70u32); assert_eq!(c.u128(), 70); ```",
"type": "string"
},
"lsts": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Array_of_LstInfo",
"type": "array",
"items": {
"$ref": "#/definitions/LstInfo"
},
"definitions": {
"LstInfo": {
"type": "object",
"required": [
"denom",
"interface"
],
"properties": {
"denom": {
"type": "string"
},
"interface": {
"type": "string"
}
},
"additionalProperties": false
}
}
},
"owner": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OwnerResponse",
Expand Down
25 changes: 25 additions & 0 deletions smart-contracts/contracts/babylon-vault/schema/raw/execute.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,31 @@
],
"properties": {
"register_lst": {
"type": "object",
"required": [
"denom",
"interface"
],
"properties": {
"denom": {
"type": "string"
},
"interface": {
"type": "string"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"unregister_lst"
],
"properties": {
"unregister_lst": {
"type": "object",
"required": [
"denom"
Expand Down
13 changes: 13 additions & 0 deletions smart-contracts/contracts/babylon-vault/schema/raw/query.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,19 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"lsts"
],
"properties": {
"lsts": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Array_of_LstInfo",
"type": "array",
"items": {
"$ref": "#/definitions/LstInfo"
},
"definitions": {
"LstInfo": {
"type": "object",
"required": [
"denom",
"interface"
],
"properties": {
"denom": {
"type": "string"
},
"interface": {
"type": "string"
}
},
"additionalProperties": false
}
}
}
45 changes: 42 additions & 3 deletions smart-contracts/contracts/babylon-vault/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use crate::error::VaultError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use crate::state::OWNER;
use crate::msg::{ExecuteMsg, InstantiateMsg, LstInfo, QueryMsg};
use crate::state::{LSTS, OWNER};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response};
use cosmwasm_std::{
to_json_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
};
use cw2::set_contract_version;

const CONTRACT_NAME: &str = "quasar:babylon-vault";
Expand Down Expand Up @@ -31,14 +33,51 @@ pub fn instantiate(
pub fn execute(deps: DepsMut, _env: Env, info: MessageInfo, msg: ExecuteMsg) -> VaultResult {
match msg {
ExecuteMsg::UpdateOwner(update) => Ok(OWNER.update(deps, info, update)?),
ExecuteMsg::RegisterLst { denom, interface } => register_lst(deps, info, denom, interface),
ExecuteMsg::UnregisterLst { denom } => unregister_lst(deps, info, denom),
_ => Ok(Response::default()),
}
}

fn register_lst(deps: DepsMut, info: MessageInfo, denom: String, interface: String) -> VaultResult {
OWNER.assert_owner(deps.storage, &info.sender)?;
LSTS.save(deps.storage, denom, &deps.api.addr_validate(&interface)?)?;
Ok(Response::default())
}

fn unregister_lst(deps: DepsMut, info: MessageInfo, denom: String) -> VaultResult {
OWNER.assert_owner(deps.storage, &info.sender)?;
let interface = LSTS.may_load(deps.storage, denom.clone())?;
if interface.is_some() {
LSTS.remove(deps.storage, denom);
Ok(Response::default())
} else {
Err(VaultError::LstNotFound { denom })
}
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> VaultResult<Binary> {
match msg {
QueryMsg::Owner {} => Ok(to_json_binary(&OWNER.query(deps.storage)?)?),
QueryMsg::Lsts {} => Ok(to_json_binary(&query_lsts(deps)?)?),
_ => Ok(Binary::default()),
}
}

fn query_lsts(deps: Deps) -> StdResult<Vec<LstInfo>> {
let lsts: StdResult<Vec<(String, Addr)>> = LSTS
.range(deps.storage, None, None, cosmwasm_std::Order::Ascending)
.collect();
let lsts = lsts?;
let infos: Vec<LstInfo> = lsts
.into_iter()
.map(|(denom, interface)| -> LstInfo {
LstInfo {
denom,
interface: interface.to_string(),
}
})
.collect();
Ok(infos)
}
3 changes: 3 additions & 0 deletions smart-contracts/contracts/babylon-vault/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,7 @@ pub enum VaultError {

#[error("{0}")]
Owner(#[from] OwnerError),

#[error("{denom} not found")]
LstNotFound { denom: String },
}
12 changes: 12 additions & 0 deletions smart-contracts/contracts/babylon-vault/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ pub enum ExecuteMsg {
// owner methods
RegisterLst {
denom: String,
interface: String,
},
UnregisterLst {
denom: String,
},
UpdateOwner(OwnerUpdate),
}
Expand All @@ -28,6 +32,12 @@ pub struct Claim {
pub expiration: Timestamp,
}

#[cw_serde]
pub struct LstInfo {
pub denom: String,
pub interface: String,
}

#[cw_serde]
#[derive(cw_orch::QueryFns, QueryResponses)]
pub enum QueryMsg {
Expand All @@ -39,4 +49,6 @@ pub enum QueryMsg {
BalanceInUnderlying {},
#[returns(OwnerResponse)]
Owner {},
#[returns(Vec<LstInfo>)]
Lsts {},
}
3 changes: 3 additions & 0 deletions smart-contracts/contracts/babylon-vault/src/state.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use cosmwasm_std::Addr;
use cw_storage_plus::Map;
use mars_owner::Owner;

pub const OWNER: Owner = Owner::new("owner");
pub const LSTS: Map<String, Addr> = Map::new("lsts");
1 change: 1 addition & 0 deletions smart-contracts/contracts/babylon-vault/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod instantiate;
pub mod register;
pub mod setup;
96 changes: 96 additions & 0 deletions smart-contracts/contracts/babylon-vault/src/tests/register.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use cosmwasm_std::Addr;
use cw_orch::contract::interface_traits::CallAs;
use mars_owner::OwnerError;

use crate::{
msg::{ExecuteMsgFns, LstInfo, QueryMsgFns},
tests::setup::{setup, OWNER},
VaultError,
};

#[test]
fn register_lst_fails_for_non_owner() {
let env = setup();
let vault = env.vault;

let lst_denom = "lst".to_string();
let interface = "interface".to_string();
let result = vault.register_lst(lst_denom, interface);
assert!(result.is_err());
assert_eq!(
result.unwrap_err().downcast::<VaultError>().unwrap(),
VaultError::Owner(OwnerError::NotOwner {})
);
}

#[test]
fn unregister_lst_fails_for_non_owner() {
let env = setup();
let vault = env.vault;

let lst_denom = "lst".to_string();
let result = vault.unregister_lst(lst_denom);
assert!(result.is_err());
assert_eq!(
result.unwrap_err().downcast::<VaultError>().unwrap(),
VaultError::Owner(OwnerError::NotOwner {})
);
}

#[test]
fn register_and_unregister_lst() {
let env = setup();
let mut vault = env.vault;
vault.set_sender(&Addr::unchecked(OWNER));

let lst_denom = "lst".to_string();
let interface = "interface".to_string();
assert!(vault
.register_lst(lst_denom.clone(), interface.clone())
.is_ok());

let lsts = vault.lsts().unwrap();
assert_eq!(lsts.len(), 1);
assert_eq!(
lsts[0],
LstInfo {
denom: lst_denom.clone(),
interface
}
);

assert!(vault.unregister_lst(lst_denom).is_ok());
let lsts = vault.lsts().unwrap();
assert_eq!(lsts.len(), 0);
}

#[test]
fn unregister_fails_if_denom_is_not_registered() {
let env = setup();
let mut vault = env.vault;
vault.set_sender(&Addr::unchecked(OWNER));

let lst_denom = "lst".to_string();
let interface = "interface".to_string();
assert!(vault
.register_lst(lst_denom.clone(), interface.clone())
.is_ok());

let lsts = vault.lsts().unwrap();
assert_eq!(lsts.len(), 1);
assert_eq!(
lsts[0],
LstInfo {
denom: lst_denom.clone(),
interface
}
);

let lst_denom = "other_lst".to_string();
let err = vault.unregister_lst(lst_denom.clone()).unwrap_err();

assert_eq!(
err.downcast::<VaultError>().unwrap(),
VaultError::LstNotFound { denom: lst_denom }
);
}
Loading

0 comments on commit c824eb8

Please sign in to comment.