Skip to content

Commit

Permalink
Wired up tick price
Browse files Browse the repository at this point in the history
  • Loading branch information
crnbarr93 committed Feb 27, 2024
1 parent 6d4189d commit cb4c27c
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
21 changes: 10 additions & 11 deletions contracts/orderbook/src/order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use crate::constants::{MAX_TICK, MIN_TICK};
use crate::error::ContractError;
use crate::state::ORDERBOOKS;
use crate::state::*;
use crate::tick_math::{multiply_by_price, tick_to_price};
use crate::types::{Fulfillment, LimitOrder, MarketOrder, OrderDirection, REPLY_ID_REFUND};
use cosmwasm_std::{
coin, ensure, ensure_eq, ensure_ne, BankMsg, Decimal, DepsMut, Env, MessageInfo, Order,
coin, ensure, ensure_eq, ensure_ne, BankMsg, Decimal256, DepsMut, Env, MessageInfo, Order,
Response, Storage, SubMsg, Uint128,
};
use cw_storage_plus::Bound;
Expand Down Expand Up @@ -158,6 +159,7 @@ pub fn run_market_order(
) -> Result<(Vec<Fulfillment>, BankMsg), ContractError> {
let mut fulfillments: Vec<Fulfillment> = vec![];
let mut amount_fulfilled: Uint128 = Uint128::zero();
let mut amount_to_send: Uint128 = Uint128::zero();
let orderbook = ORDERBOOKS.load(storage, &order.book_id)?;
let placed_order_denom = orderbook.get_expected_denom(&order.order_direction);

Expand Down Expand Up @@ -200,7 +202,7 @@ pub fn run_market_order(

for maybe_current_tick in ticks {
let current_tick = maybe_current_tick?.0;

let tick_price: Decimal256 = tick_to_price(current_tick)?;
// Create orders iterator for all orders on current tick
let tick_orders = orders().prefix((order.book_id, current_tick)).range(
storage,
Expand All @@ -219,42 +221,41 @@ pub fn run_market_order(
let fill_quantity = order.quantity.min(current_order.quantity);
// Add to total amount fulfilled from placed order
amount_fulfilled = amount_fulfilled.checked_add(fill_quantity)?;
amount_to_send =
amount_to_send.checked_add(multiply_by_price(amount_fulfilled, tick_price)?)?;
// Generate fulfillment for current order
let fulfillment = Fulfillment::new(current_order, fill_quantity);
fulfillments.push(fulfillment);

// Update remaining order quantity
order.quantity = order.quantity.checked_sub(fill_quantity)?;
// TODO: Price detection
if order.quantity.is_zero() {
return Ok((
fulfillments,
BankMsg::Send {
to_address: order.owner.to_string(),
amount: vec![coin(amount_fulfilled.u128(), placed_order_denom)],
amount: vec![coin(amount_to_send.u128(), placed_order_denom)],
},
));
}
}

// TODO: Price detection
if order.quantity.is_zero() {
return Ok((
fulfillments,
BankMsg::Send {
to_address: order.owner.to_string(),
amount: vec![coin(amount_fulfilled.u128(), placed_order_denom)],
amount: vec![coin(amount_to_send.u128(), placed_order_denom)],
},
));
}
}

// TODO: Price detection
Ok((
fulfillments,
BankMsg::Send {
to_address: order.owner.to_string(),
amount: vec![coin(amount_fulfilled.u128(), placed_order_denom)],
amount: vec![coin(amount_to_send.u128(), placed_order_denom)],
},
))
}
Expand All @@ -280,9 +281,7 @@ pub fn resolve_fulfillments(
);
let denom = orderbook.get_expected_denom(&fulfillment.order.order_direction);
// TODO: Add price detection for tick
let msg = fulfillment
.order
.fill(&denom, fulfillment.amount, Decimal::one())?;
let msg = fulfillment.order.fill(&denom, fulfillment.amount)?;
msgs.push(msg);
if fulfillment.order.quantity.is_zero() {
orders().remove(
Expand Down
4 changes: 2 additions & 2 deletions contracts/orderbook/src/tests/test_order.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ fn test_resolve_fulfillments() {
Fulfillment::new(
LimitOrder::new(
0,
1,
MAX_TICK,
1,
OrderDirection::Bid,
Addr::unchecked("creator"),
Expand Down Expand Up @@ -837,7 +837,7 @@ fn test_resolve_fulfillments() {
// Check message is generated as expected
let mut order = order.clone();
let denom = orderbook.get_expected_denom(&order.order_direction);
let msg = order.fill(denom, *amount, Decimal::one()).unwrap();
let msg = order.fill(denom, *amount).unwrap();

assert_eq!(response[idx], msg, "{}", format_test_name(test.name));
}
Expand Down
22 changes: 21 additions & 1 deletion contracts/orderbook/src/tick_math.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::str::FromStr;

use crate::constants::{
EXPONENT_AT_PRICE_ONE, GEOMETRIC_EXPONENT_INCREMENT_DISTANCE_IN_TICKS, MAX_TICK, MIN_TICK,
};
use crate::error::*;
use cosmwasm_std::{ensure, Decimal256, Uint256};
use cosmwasm_std::{ensure, Decimal256, Uint128, Uint256};

// tick_to_price converts a tick index to a price.
// If tick_index is zero, the function returns Decimal256::one().
Expand Down Expand Up @@ -72,3 +74,21 @@ pub fn pow_ten(expo: i32) -> ContractResult<Decimal256> {
Ok(Decimal256::from_ratio(res, Uint256::one()))
}
}

// Multiplies a given tick amount by the price for that tick
pub fn multiply_by_price(amount: Uint128, price: Decimal256) -> ContractResult<Uint128> {
let amount_to_send_u256 = price
.checked_mul(Decimal256::new(Uint256::from(amount)))?
.to_uint_ceil();

// TODO: Rounding?
ensure!(
amount_to_send_u256 <= Uint256::from_u128(Uint128::MAX.u128()),
ContractError::InvalidQuantity {
quantity: Uint128::MAX
}
);
let amount_to_send = Uint128::from_str(amount_to_send_u256.to_string().as_str()).unwrap();

Ok(amount_to_send)
}
16 changes: 8 additions & 8 deletions contracts/orderbook/src/types/order.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{coin, ensure, Addr, BankMsg, Decimal, Uint128};
use cosmwasm_std::{coin, ensure, Addr, BankMsg, Uint128};

use crate::ContractError;
use crate::{
tick_math::{multiply_by_price, tick_to_price},
ContractError,
};

#[cw_serde]
#[derive(Copy)]
Expand Down Expand Up @@ -44,7 +47,6 @@ impl LimitOrder {
&mut self,
denom: impl Into<String>,
quantity: Uint128,
price: Decimal,
) -> Result<BankMsg, ContractError> {
ensure!(
self.quantity >= quantity,
Expand All @@ -57,13 +59,11 @@ impl LimitOrder {
}
);
self.quantity = self.quantity.checked_sub(quantity)?;
let price = tick_to_price(self.tick_id)?;
let amount_to_send = multiply_by_price(quantity, price)?;
Ok(BankMsg::Send {
to_address: self.owner.to_string(),
amount: vec![coin(
// TODO: Add From for error
quantity.checked_mul_floor(price).unwrap().u128(),
denom.into(),
)],
amount: vec![coin(amount_to_send.u128(), denom.into())],
})
}
}
Expand Down

0 comments on commit cb4c27c

Please sign in to comment.