Skip to content

Commit

Permalink
Cleanup coinlist (#797)
Browse files Browse the repository at this point in the history
  • Loading branch information
lubkoll authored Aug 21, 2024
1 parent 1881e78 commit fa08640
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 127 deletions.
167 changes: 41 additions & 126 deletions smart-contracts/osmosis/contracts/cl-vault/src/helpers/coinlist.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{coin, Attribute, BankMsg, Coin, CosmosMsg, Decimal, Fraction, Uint128};
use cosmwasm_std::{
coin, Attribute, BankMsg, CheckedMultiplyFractionError, Coin, CosmosMsg, Decimal, Uint128,
};
use osmosis_std::types::cosmos::base::v1beta1::Coin as OsmoCoin;

use crate::ContractError;

use super::generic::sort_tokens;

/// COIN LIST
#[cw_serde]
#[derive(Default)]
pub struct CoinList(Vec<Coin>);
Expand All @@ -18,25 +18,23 @@ impl CoinList {
}

/// calculates the ratio of the current rewards
pub fn mul_ratio(&self, ratio: Decimal) -> CoinList {
pub fn mul_ratio(&self, ratio: Decimal) -> Result<CoinList, CheckedMultiplyFractionError> {
if ratio == Decimal::zero() {
// Return an empty list if the ratio is zero.
return CoinList::new();
return Ok(CoinList::new());
}

CoinList(
self.0
.iter()
.map(|c| {
coin(
c.amount
.multiply_ratio(ratio.numerator(), ratio.denominator())
.u128(),
c.denom.clone(),
)
})
.collect(),
)
let coins: Result<Vec<_>, _> = self
.0
.iter()
.map(|c| -> Result<Coin, CheckedMultiplyFractionError> {
Ok(coin(
c.amount.checked_mul_floor(ratio)?.u128(),
c.denom.clone(),
))
})
.collect();
Ok(CoinList(coins?))
}

pub fn is_empty(&self) -> bool {
Expand All @@ -50,24 +48,10 @@ impl CoinList {
.map(|c| Ok(coin(c.amount.parse()?, c.denom.clone())))
.collect();

// Append and merge to
self.merge(parsed_rewards?)?;
Ok(())
}

pub fn update_rewards_coin_list(&mut self, rewards: CoinList) -> Result<(), ContractError> {
let parsed_rewards: Result<Vec<Coin>, ContractError> = rewards
.coins()
.into_iter()
.map(|c| Ok(coin(c.amount.u128(), c.denom)))
.collect();

// Append and merge to
self.merge(parsed_rewards?)?;
Ok(())
}

/// add rewards to self and mutate self
pub fn add(&mut self, rewards: CoinList) -> Result<(), ContractError> {
self.merge(rewards.coins())?;
Ok(())
Expand All @@ -85,20 +69,17 @@ impl CoinList {
Ok(())
}

/// Subtracts a percentage from self, mutate self and return the subtracted rewards,
/// excluding any coins with zero amounts.
/// Subtracts a percentage from self and return the subtracted rewards,
pub fn sub_ratio(&mut self, ratio: Decimal) -> Result<CoinList, ContractError> {
let to_sub = self.mul_ratio(ratio);

// Actually subtract the funds
let to_sub = self.mul_ratio(ratio)?;
self.sub(&to_sub)?;

// Return only coins with non-zero amounts, filtering out any zeros that might result from the subtraction.
Ok(CoinList(
to_sub
.0
.into_iter()
.iter()
.filter(|c| c.amount != Uint128::zero())
.cloned()
.collect(),
))
}
Expand Down Expand Up @@ -141,10 +122,13 @@ impl CoinList {
}

pub fn coins(&self) -> Vec<Coin> {
sort_tokens(self.0.clone())
.into_iter()
.filter(|c| c.amount > Uint128::zero())
.collect()
sort_tokens(
self.0
.iter()
.filter(|c| c.amount > Uint128::zero())
.cloned()
.collect(),
)
}

pub fn from_coins(coins: Vec<Coin>) -> Self {
Expand Down Expand Up @@ -306,7 +290,9 @@ mod tests {
])
.unwrap();

let ratio = rewards.mul_ratio(Decimal::from_ratio(Uint128::new(10), Uint128::new(100)));
let ratio = rewards
.mul_ratio(Decimal::from_ratio(Uint128::new(10), Uint128::new(100)))
.unwrap();
assert_eq!(
ratio,
CoinList(vec![
Expand All @@ -319,23 +305,11 @@ mod tests {

#[test]
fn sub_percentage_works() {
let mut rewards = CoinList::new();
rewards
.update_rewards(&[
OsmoCoin {
denom: "uosmo".into(),
amount: "1000".into(),
},
OsmoCoin {
denom: "uatom".into(),
amount: "2000".into(),
},
OsmoCoin {
denom: "uqsr".into(),
amount: "3000".into(),
},
])
.unwrap();
let mut rewards = CoinList::from_coins(vec![
coin(1000, "uosmo"),
coin(2000, "uatom"),
coin(3000, "uqsr"),
]);

let ratio = rewards
.sub_ratio(Decimal::from_ratio(Uint128::new(10), Uint128::new(100)))
Expand Down Expand Up @@ -363,23 +337,12 @@ mod tests {

#[test]
fn add_works() {
let mut rewards = CoinList::new();
rewards
.update_rewards(&[
OsmoCoin {
denom: "uosmo".into(),
amount: "1000".into(),
},
OsmoCoin {
denom: "uatom".into(),
amount: "2000".into(),
},
OsmoCoin {
denom: "uqsr".into(),
amount: "3000".into(),
},
])
.unwrap();
let mut rewards = CoinList::from_coins(vec![
coin(1000, "uosmo"),
coin(2000, "uatom"),
coin(3000, "uqsr"),
]);

rewards
.add(CoinList::from_coins(vec![
coin(2000, "uosmo"),
Expand All @@ -398,52 +361,4 @@ mod tests {
])
)
}

#[test]
fn update_rewards_works() {
let mut rewards = CoinList::new();
rewards
.update_rewards(&[
OsmoCoin {
denom: "uosmo".into(),
amount: "1000".into(),
},
OsmoCoin {
denom: "uatom".into(),
amount: "2000".into(),
},
OsmoCoin {
denom: "uqsr".into(),
amount: "3000".into(),
},
])
.unwrap();

rewards
.update_rewards(&[
OsmoCoin {
denom: "uosmo".into(),
amount: "1000".into(),
},
OsmoCoin {
denom: "umars".into(),
amount: "1234".into(),
},
OsmoCoin {
denom: "uqsr".into(),
amount: "3000".into(),
},
])
.unwrap();

assert_eq!(
rewards,
CoinList::from_coins(vec![
coin(2000, "uosmo"),
coin(2000, "uatom"),
coin(6000, "uqsr"),
coin(1234, "umars")
])
);
}
}
2 changes: 1 addition & 1 deletion smart-contracts/osmosis/contracts/cl-vault/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub fn query_assets_from_shares(

let vault_balance = CoinList::from_coins(vec![vault_assets.token0, vault_assets.token1]);

let assets_from_shares = vault_balance.mul_ratio(Decimal::from_ratio(shares, vault_supply));
let assets_from_shares = vault_balance.mul_ratio(Decimal::from_ratio(shares, vault_supply))?;

Ok(AssetsBalanceResponse {
balances: assets_from_shares.coins(),
Expand Down

0 comments on commit fa08640

Please sign in to comment.