Skip to content

Commit

Permalink
program: add recenter amm ix (#836)
Browse files Browse the repository at this point in the history
* bigz/add-amm-recenter-fcn

* add recenter-amm-2 test

* passing recenter_amm_2 test

* add test_move_amm test

* update todo msg

* add to adminClient

* add get_lower_bound_sqrt_k functor

* CHANGELOG

---------

Co-authored-by: Chris Heaney <[email protected]>
  • Loading branch information
0xbigz and crispheaney committed Jan 26, 2024
1 parent f19ed36 commit 2223241
Show file tree
Hide file tree
Showing 10 changed files with 694 additions and 11 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

### Fixes
- program: add recenter amm ix ([#836](https://github.com/drift-labs/protocol-v2/pull/836))

- program: enable jit maker to fill same slot as taker placed ([#835](https://github.com/drift-labs/protocol-v2/pull/835))
### Fixes

### Breaking

Expand Down
53 changes: 53 additions & 0 deletions programs/drift/src/controller/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,10 +745,63 @@ pub fn move_price(
validate!(
(quote_asset_reserve.cast::<i128>()? - amm.quote_asset_reserve.cast::<i128>()?).abs() < 100,
ErrorCode::InvalidAmmDetected,
"quote_asset_reserve passed doesnt reconcile enough {} vs {}",
quote_asset_reserve.cast::<i128>()?,
amm.quote_asset_reserve.cast::<i128>()?
)?;

amm.sqrt_k = sqrt_k;

let (_, terminal_quote_reserves, terminal_base_reserves) =
amm::calculate_terminal_price_and_reserves(amm)?;
amm.terminal_quote_asset_reserve = terminal_quote_reserves;

let (min_base_asset_reserve, max_base_asset_reserve) =
amm::calculate_bid_ask_bounds(amm.concentration_coef, terminal_base_reserves)?;

amm.max_base_asset_reserve = max_base_asset_reserve;
amm.min_base_asset_reserve = min_base_asset_reserve;

let reserve_price_after = amm.reserve_price()?;
update_spreads(amm, reserve_price_after)?;

Ok(())
}

// recenter peg with balanced terminal reserves
pub fn recenter_perp_market_amm(amm: &mut AMM, peg_multiplier: u128, sqrt_k: u128) -> DriftResult {
// calculate base/quote reserves for balanced terminal reserves
let swap_direction = if amm.base_asset_amount_with_amm > 0 {
SwapDirection::Remove
} else {
SwapDirection::Add
};
let (new_quote_asset_amount, new_base_asset_amount) = amm::calculate_swap_output(
amm.base_asset_amount_with_amm.unsigned_abs(),
sqrt_k,
swap_direction,
sqrt_k,
)?;

amm.base_asset_reserve = new_base_asset_amount;

let k = bn::U256::from(sqrt_k).safe_mul(bn::U256::from(sqrt_k))?;

amm.quote_asset_reserve = k
.safe_div(bn::U256::from(new_base_asset_amount))?
.try_to_u128()?;

validate!(
(new_quote_asset_amount.cast::<i128>()? - amm.quote_asset_reserve.cast::<i128>()?).abs()
< 100,
ErrorCode::InvalidAmmDetected,
"quote_asset_reserve passed doesnt reconcile enough"
)?;

amm.sqrt_k = sqrt_k;
// todo: could calcualte terminal state cost for altering sqrt_k

amm.peg_multiplier = peg_multiplier;

let (_, terminal_quote_reserves, terminal_base_reserves) =
amm::calculate_terminal_price_and_reserves(amm)?;
Expand Down
319 changes: 313 additions & 6 deletions programs/drift/src/controller/position/tests.rs

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,21 @@ pub fn handle_move_amm_price(
Ok(())
}

#[access_control(
perp_market_valid(&ctx.accounts.perp_market)
)]
pub fn handle_recenter_perp_market_amm(
ctx: Context<AdminUpdatePerpMarket>,
peg_multiplier: u128,
sqrt_k: u128,
) -> Result<()> {
let perp_market = &mut load_mut!(ctx.accounts.perp_market)?;
controller::amm::recenter_perp_market_amm(&mut perp_market.amm, peg_multiplier, sqrt_k)?;
validate_perp_market(perp_market)?;

Ok(())
}

#[access_control(
perp_market_valid(&ctx.accounts.perp_market)
)]
Expand Down Expand Up @@ -1166,7 +1181,7 @@ pub fn handle_update_k(ctx: Context<AdminUpdateK>, sqrt_k: u128) -> Result<()> {

let update_k_result = get_update_k_result(perp_market, new_sqrt_k_u192, true)?;

let adjustment_cost = math::cp_curve::adjust_k_cost(perp_market, &update_k_result)?;
let adjustment_cost: i128 = math::cp_curve::adjust_k_cost(perp_market, &update_k_result)?;

math::cp_curve::update_k(perp_market, &update_k_result)?;

Expand Down
8 changes: 8 additions & 0 deletions programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,14 @@ pub mod drift {
handle_move_amm_price(ctx, base_asset_reserve, quote_asset_reserve, sqrt_k)
}

pub fn recenter_perp_market_amm(
ctx: Context<AdminUpdatePerpMarket>,
peg_multiplier: u128,
sqrt_k: u128,
) -> Result<()> {
handle_recenter_perp_market_amm(ctx, peg_multiplier, sqrt_k)
}

pub fn update_perp_market_expiry(
ctx: Context<AdminUpdatePerpMarket>,
expiry_ts: i64,
Expand Down
5 changes: 4 additions & 1 deletion programs/drift/src/math/repeg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,14 @@ pub fn adjust_amm(
let adjustment_cost: i128 = if adjust_k && can_lower_k {
// TODO can be off by 1?

// always let protocol-owned sqrt_k be either least .1% of lps or the base amount / min order
let new_sqrt_k_lower_bound = market.amm.get_lower_bound_sqrt_k()?;

let new_sqrt_k = market
.amm
.sqrt_k
.safe_sub(market.amm.sqrt_k.safe_div(1000)?)?
.max(market.amm.user_lp_shares.safe_add(1)?);
.max(new_sqrt_k_lower_bound);

let update_k_result =
cp_curve::get_update_k_result(market, bn::U192::from(new_sqrt_k), true)?;
Expand Down
9 changes: 9 additions & 0 deletions programs/drift/src/state/perp_market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,15 @@ impl AMM {
}
}

pub fn get_lower_bound_sqrt_k(self) -> DriftResult<u128> {
Ok(self.sqrt_k.min(
self.user_lp_shares
.safe_add(self.user_lp_shares.safe_div(1000)?)?
.max(self.min_order_size.cast()?)
.max(self.base_asset_amount_with_amm.unsigned_abs().cast()?),
))
}

pub fn get_protocol_owned_position(self) -> DriftResult<i64> {
self.base_asset_amount_with_amm
.safe_add(self.base_asset_amount_with_unsettled_lp)?
Expand Down
26 changes: 26 additions & 0 deletions sdk/src/adminClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,32 @@ export class AdminClient extends DriftClient {
return txSig;
}

public async recenterPerpMarketAmm(
perpMarketIndex: number,
pegMultiplier: BN,
sqrtK: BN
): Promise<TransactionSignature> {
const marketPublicKey = await getPerpMarketPublicKey(
this.program.programId,
perpMarketIndex
);

const tx = await this.program.transaction.recenterPerpMarketAmm(
pegMultiplier,
sqrtK,
{
accounts: {
state: await this.getStatePublicKey(),
admin: this.wallet.publicKey,
perpMarket: marketPublicKey,
},
}
);

const { txSig } = await this.sendTransaction(tx, [], this.opts);
return txSig;
}

public async updatePerpMarketConcentrationScale(
perpMarketIndex: number,
concentrationScale: BN
Expand Down
30 changes: 30 additions & 0 deletions sdk/src/idl/drift.json
Original file line number Diff line number Diff line change
Expand Up @@ -2972,6 +2972,36 @@
}
]
},
{
"name": "recenterPerpMarketAmm",
"accounts": [
{
"name": "admin",
"isMut": false,
"isSigner": true
},
{
"name": "state",
"isMut": false,
"isSigner": false
},
{
"name": "perpMarket",
"isMut": true,
"isSigner": false
}
],
"args": [
{
"name": "pegMultiplier",
"type": "u128"
},
{
"name": "sqrtK",
"type": "u128"
}
]
},
{
"name": "updatePerpMarketExpiry",
"accounts": [
Expand Down
Loading

0 comments on commit 2223241

Please sign in to comment.