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

Bigz/add amm recenter fcn #836

Merged
merged 10 commits into from
Jan 26, 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
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
Loading