Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perp-4102 | burn half of the house LP shares #29

Merged
merged 3 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion contract/src/cpmm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ impl AddLiquidity {
storage: &mut dyn Storage,
market: &mut StoredMarket,
sender: &Addr,
burn_half: bool,
) -> Result<()> {
assert_eq!(market.outcomes.len(), self.returned_to_user.len());
let AddLiquidity {
lp,
returned_to_user,
added_to_pool: _,
} = self;
let lp = if burn_half {
LpShare(lp.0 / Uint256::from(2u8))
} else {
lp
};
market.lp_shares += lp;
let mut share_info = ShareInfo::load(storage, market, sender)?
.unwrap_or_else(|| ShareInfo::new(market.outcomes.len()));
share_info.shares += lp;
Expand Down Expand Up @@ -85,7 +92,6 @@ impl StoredMarket {
}

let new_shares = LpShare(funds.0 * self.lp_shares.0 / pool_weight.0);
self.lp_shares += new_shares;

AddLiquidity {
lp: new_shares,
Expand Down Expand Up @@ -114,6 +120,7 @@ impl StoredMarket {
returned_to_user: mut pending_tokens,
added_to_pool: _,
} = self.add_liquidity(liquidity_funds);
self.lp_shares += lp;

// Now we can add the remaining funds to the pool and mint an appropriate number of tokens.
let funds = funds - liquidity_funds;
Expand Down
10 changes: 5 additions & 5 deletions contract/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ fn deposit(
let house = market.house.clone();
market
.add_liquidity(fee)
.assign_to(deps.storage, &mut market, &house)?;
.assign_to(deps.storage, &mut market, &house, true)?;
let funds = deposit_amount.checked_sub(fee)?;
let Buy { lp, tokens } = market.buy(outcome, funds, liquidity)?;

Expand Down Expand Up @@ -297,7 +297,7 @@ fn provide(
),
);

add_liquidity.assign_to(deps.storage, &mut market, &info.sender)?;
add_liquidity.assign_to(deps.storage, &mut market, &info.sender, false)?;
MARKETS.save(deps.storage, market.id, &market)?;

Ok(res)
Expand Down Expand Up @@ -342,7 +342,7 @@ fn withdraw(

let Sell { funds, returned } = market.sell(outcome, tokens)?;

if share_info.get_outcome(&market, outcome)?.is_zero() {
if share_info.get_outcome(&market, outcome, false)?.is_zero() {
market.get_outcome_mut(outcome)?.wallets -= 1;
if !share_info.has_tokens() {
market.total_wallets -= 1;
Expand Down Expand Up @@ -373,7 +373,7 @@ fn withdraw(
let house = market.house.clone();
market
.add_liquidity(fee)
.assign_to(deps.storage, &mut market, &house)?;
.assign_to(deps.storage, &mut market, &house, true)?;
let funds = funds.checked_sub(fee)?;
MARKETS.save(deps.storage, id, &market)?;
Ok(Response::new()
Expand Down Expand Up @@ -441,7 +441,7 @@ fn collect(deps: &mut DepsMut, info: MessageInfo, id: MarketId) -> Result<Respon
return Err(Error::AlreadyClaimedWinnings { id });
}
share_info.claimed_winnings = true;
let tokens = share_info.get_outcome(&market, winner)?;
let tokens = share_info.get_outcome(&market, winner, true)?;
if tokens.is_zero() {
return Err(Error::NoTokensFound {
id,
Expand Down
1 change: 1 addition & 0 deletions contract/src/sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub fn sanity(store: &dyn Storage, env: &Env) {
assert_eq!(tokens.0, pool_size.0);
}

// FIXME modify check to include in all wallets if they have a liquidity share
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you want to address this as part of this PR or later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in the next PR.

assert_eq!(computed_total_wallets, total_wallets);

for outcome in &market_outcomes {
Expand Down
35 changes: 22 additions & 13 deletions contract/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ impl ShareInfo {
HOLDERS.save(store, (market.id, addr), self)
}

pub(crate) fn get_outcome(&self, market: &StoredMarket, outcome: OutcomeId) -> Result<Token> {
pub(crate) fn get_outcome(
&self,
market: &StoredMarket,
outcome: OutcomeId,
include_pool: bool,
) -> Result<Token> {
let from_tokens =
self.outcomes
.get(outcome.usize())
Expand All @@ -48,18 +53,22 @@ impl ShareInfo {
outcome_count: self.outcomes.len().to_string(),
outcome,
})?;
let from_pool = market
.outcomes
.get(outcome.usize())
.as_ref()
.ok_or_else(|| Error::InvalidOutcome {
id: market.id,
outcome_count: self.outcomes.len().to_string(),
outcome,
})?
.pool_tokens
* (self.shares / market.lp_shares);
Ok(from_tokens + from_pool)
if include_pool {
let from_pool = market
.outcomes
.get(outcome.usize())
.as_ref()
.ok_or_else(|| Error::InvalidOutcome {
id: market.id,
outcome_count: self.outcomes.len().to_string(),
outcome,
})?
.pool_tokens
* (self.shares / market.lp_shares);
Ok(from_tokens + from_pool)
} else {
Ok(from_tokens)
}
}

pub(crate) fn get_outcome_mut(
Expand Down
48 changes: 44 additions & 4 deletions contract/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,19 @@ impl Predict {
self.query(&QueryMsg::GlobalInfo {})
}

fn query_holder(&self, better: &Addr) -> StdResult<PositionsResp> {
self.query(&QueryMsg::Positions {
id: self.id,
addr: better.to_string(),
})
}

fn query_tokens(&self, better: &Addr, outcome: u8) -> StdResult<Token> {
let PositionsResp {
outcomes,
claimed_winnings: _,
shares: _,
} = self.query(&QueryMsg::Positions {
id: self.id,
addr: better.to_string(),
})?;
} = self.query_holder(better)?;
outcomes
.get(usize::from(outcome))
.copied()
Expand Down Expand Up @@ -652,6 +656,42 @@ fn change_admin() {
assert_eq!(global_info.admin, app.better);
}

#[test]
fn bet_with_liquidity() {
let app = Predict::new();

// Better places a bet that includes providing liquidity.
// Confirm that the number of shares held by the house increases.
let house_shares1 = app.query_holder(&app.house).unwrap().shares;
app.place_bet(&app.better, 0, 1_000).unwrap();
let house_shares2 = app.query_holder(&app.house).unwrap().shares;
assert!(house_shares2 > house_shares1);

// The better shouldn't have any LP shares yet. Now do another bet
// that includes providing liquidity.
assert_eq!(
app.query_holder(&app.better).unwrap().shares,
LpShare::zero()
);
app.place_bet_with(&app.better, 0, 1_000, "0.1".parse().unwrap())
.unwrap();
assert_ne!(
app.query_holder(&app.better).unwrap().shares,
LpShare::zero()
);

// The house's LP token count should have gone up
let house_shares3 = app.query_holder(&app.house).unwrap().shares;
assert!(house_shares3 > house_shares2);

// Rusty: I'd originally intended to write a test showing that the LP share value
// for the better went up. However, after implementing such a test, I realized
// (through failing tests) that you can't compare based on the number of tokens
// per LP share, since the balance of tokens within the pool changes from each
// buy or sell action. Leaving this test as-is unless we can come up with something
// better.
}

#[test]
fn cannot_bet_liquidity_of_one() {
let app = Predict::new();
Expand Down
4 changes: 3 additions & 1 deletion contract/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,9 @@ impl TryFrom<usize> for OutcomeId {
}
}

#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug, Copy, PartialEq, Eq)]
#[derive(
Clone, Serialize, Deserialize, JsonSchema, Debug, Copy, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct LpShare(pub Uint256);
impl LpShare {
pub(crate) fn zero() -> LpShare {
Expand Down
Loading