Skip to content

Commit

Permalink
program: account for fuel in swaps(#1411)
Browse files Browse the repository at this point in the history
* program: user-increment-bonus-swap

* fix delta

* clean up

* CHANGELOG

* add test

* Prettify

* Prettify

* Prettify

* sdk: release v2.105.0-beta.5

* v2.105.0

* sdk: release v2.106.0-beta.0

* sdk: add calculateBaseAssetAmountToCoverMarginShortage (#1409)

* sdk: add calculateBaseAssetAmountToCoverMarginShortage

* add calculateMaxPctToLiquidate

* prettify

* sdk: release v2.106.0-beta.1

* Nour/swift subscriber (#1408)

* add endpoint optionality to swift order subscriber

* add to export barrel file

* add utility ix to getplaceandmakeswiftixs

* sdk: release v2.106.0-beta.2

* sdk: add spot-market-index-33-34-pool-1 constants (#1412)

* sdk: release v2.106.0-beta.3

* add signed fuelboostdeposit

* tests/spotSwap.ts: add commented out assert

* CHANGELOG

---------

Co-authored-by: Chris Heaney <[email protected]>
Co-authored-by: Luke Steyn <[email protected]>
Co-authored-by: GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: moosecat <[email protected]>
  • Loading branch information
5 people authored Jan 8, 2025
1 parent 51b7053 commit d74ae40
Show file tree
Hide file tree
Showing 9 changed files with 128 additions and 57 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixes

- program: account for fuel in swaps ([#1411](https://github.com/drift-labs/protocol-v2/pull/1411))
- program: account for fuel when there is full withdraw ([#1413](https://github.com/drift-labs/protocol-v2/pull/1413))

### Breaking
Expand All @@ -23,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixes

- program: fix spot swap fuel bonus ([#1411](https://github.com/drift-labs/protocol-v2/pull/1411))
- program: skip liq perp oracle twap check if market is in settlement ([#1406](https://github.com/drift-labs/protocol-v2/pull/1406))

### Breaking
Expand Down
22 changes: 13 additions & 9 deletions programs/drift/src/instructions/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ pub fn handle_update_spot_market_expiry(

pub fn handle_init_user_fuel(
ctx: Context<InitUserFuel>,
fuel_bonus_deposits: Option<u32>,
fuel_bonus_deposits: Option<i32>,
fuel_bonus_borrows: Option<u32>,
fuel_bonus_taker: Option<u32>,
fuel_bonus_maker: Option<u32>,
Expand All @@ -1250,19 +1250,23 @@ pub fn handle_init_user_fuel(
let user = &mut load_mut!(ctx.accounts.user)?;
let user_stats = &mut load_mut!(ctx.accounts.user_stats)?;

validate!(
user.last_fuel_bonus_update_ts < FUEL_START_TS as u32,
ErrorCode::DefaultError,
"User must not have begun earning fuel"
)?;

if let Some(fuel_bonus_deposits) = fuel_bonus_deposits {
let new_fuel_bonus_deposits = if fuel_bonus_deposits >= 0 {
user_stats
.fuel_deposits
.saturating_add(fuel_bonus_deposits.cast()?)
} else {
user_stats
.fuel_deposits
.saturating_sub(fuel_bonus_deposits.unsigned_abs())
};

msg!(
"user_stats.fuel_deposits {:?} -> {:?}",
user_stats.fuel_deposits,
user_stats.fuel_deposits.saturating_add(fuel_bonus_deposits)
new_fuel_bonus_deposits
);
user_stats.fuel_deposits = user_stats.fuel_deposits.saturating_add(fuel_bonus_deposits);
user_stats.fuel_deposits = new_fuel_bonus_deposits;
}
if let Some(fuel_bonus_borrows) = fuel_bonus_borrows {
msg!(
Expand Down
12 changes: 8 additions & 4 deletions programs/drift/src/instructions/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ use crate::math::liquidation::is_user_being_liquidated;
use crate::math::margin::meets_initial_margin_requirement;
use crate::math::margin::{
calculate_max_withdrawable_amount, meets_maintenance_margin_requirement,
meets_place_order_margin_requirement, meets_withdraw_margin_requirement,
validate_spot_margin_trading, MarginRequirementType,
meets_place_order_margin_requirement, validate_spot_margin_trading, MarginRequirementType,
};
use crate::math::safe_math::SafeMath;
use crate::math::spot_balance::get_token_value;
Expand Down Expand Up @@ -3057,12 +3056,17 @@ pub fn handle_end_swap<'c: 'info, 'info>(
drop(out_spot_market);
drop(in_spot_market);

meets_withdraw_margin_requirement(
&user,
user.meets_withdraw_margin_requirement_and_increment_fuel_bonus_swap(
&perp_market_map,
&spot_market_map,
&mut oracle_map,
margin_type,
in_market_index,
in_token_amount_before.safe_sub(in_token_amount_after)?,
out_market_index,
out_token_amount_before.safe_sub(out_token_amount_after)?,
&mut user_stats,
now,
)?;

user.update_last_active_slot(slot);
Expand Down
2 changes: 1 addition & 1 deletion programs/drift/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ pub mod drift {

pub fn init_user_fuel(
ctx: Context<InitUserFuel>,
fuel_boost_deposits: Option<u32>,
fuel_boost_deposits: Option<i32>,
fuel_boost_borrows: Option<u32>,
fuel_boost_taker: Option<u32>,
fuel_boost_maker: Option<u32>,
Expand Down
41 changes: 0 additions & 41 deletions programs/drift/src/math/margin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -665,47 +665,6 @@ pub fn validate_any_isolated_tier_requirements(
Ok(())
}

pub fn meets_withdraw_margin_requirement(
user: &User,
perp_market_map: &PerpMarketMap,
spot_market_map: &SpotMarketMap,
oracle_map: &mut OracleMap,
margin_requirement_type: MarginRequirementType,
) -> DriftResult<bool> {
let strict = margin_requirement_type == MarginRequirementType::Initial;
let context = MarginContext::standard(margin_requirement_type)
.strict(strict)
.ignore_invalid_deposit_oracles(true);

let calculation = calculate_margin_requirement_and_total_collateral_and_liability_info(
user,
perp_market_map,
spot_market_map,
oracle_map,
context,
)?;

if calculation.margin_requirement > 0 || calculation.get_num_of_liabilities()? > 0 {
validate!(
calculation.all_liability_oracles_valid,
ErrorCode::InvalidOracle,
"User attempting to withdraw with outstanding liabilities when a liability oracle is invalid"
)?;
}

validate_any_isolated_tier_requirements(user, calculation)?;

validate!(
calculation.meets_margin_requirement(),
ErrorCode::InsufficientCollateral,
"User attempting to withdraw where total_collateral {} is below initial_margin_requirement {}",
calculation.total_collateral,
calculation.margin_requirement
)?;

Ok(true)
}

pub fn meets_place_order_margin_requirement(
user: &User,
perp_market_map: &PerpMarketMap,
Expand Down
56 changes: 56 additions & 0 deletions programs/drift/src/state/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,62 @@ impl User {

Ok(margin_calculation)
}
pub fn meets_withdraw_margin_requirement_and_increment_fuel_bonus_swap(
&mut self,
perp_market_map: &PerpMarketMap,
spot_market_map: &SpotMarketMap,
oracle_map: &mut OracleMap,
margin_requirement_type: MarginRequirementType,
in_market_index: u16,
in_delta: i128,
out_market_index: u16,
out_delta: i128,
user_stats: &mut UserStats,
now: i64,
) -> DriftResult<bool> {
let strict = margin_requirement_type == MarginRequirementType::Initial;
let context = MarginContext::standard(margin_requirement_type)
.strict(strict)
.ignore_invalid_deposit_oracles(true)
.fuel_spot_deltas([(in_market_index, in_delta), (out_market_index, out_delta)])
.fuel_numerator(self, now);

let calculation = calculate_margin_requirement_and_total_collateral_and_liability_info(
self,
perp_market_map,
spot_market_map,
oracle_map,
context,
)?;

if calculation.margin_requirement > 0 || calculation.get_num_of_liabilities()? > 0 {
validate!(
calculation.all_liability_oracles_valid,
ErrorCode::InvalidOracle,
"User attempting to withdraw with outstanding liabilities when an oracle is invalid"
)?;
}

validate_any_isolated_tier_requirements(self, calculation)?;

validate!(
calculation.meets_margin_requirement(),
ErrorCode::InsufficientCollateral,
"User attempting to withdraw where total_collateral {} is below initial_margin_requirement {}",
calculation.total_collateral,
calculation.margin_requirement
)?;

user_stats.update_fuel_bonus(
self,
calculation.fuel_deposits,
calculation.fuel_borrows,
calculation.fuel_positions,
now,
)?;

Ok(true)
}

pub fn meets_withdraw_margin_requirement_and_increment_fuel_bonus(
&mut self,
Expand Down
2 changes: 1 addition & 1 deletion sdk/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.106.0-beta.6
2.106.0-beta.6
2 changes: 1 addition & 1 deletion sdk/src/idl/drift.json
Original file line number Diff line number Diff line change
Expand Up @@ -6111,7 +6111,7 @@
{
"name": "fuelBoostDeposits",
"type": {
"option": "u32"
"option": "i32"
}
},
{
Expand Down
46 changes: 46 additions & 0 deletions tests/spotSwap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
QUOTE_PRECISION,
UserStatsAccount,
getUserStatsAccountPublicKey,
FUEL_WINDOW,
} from '../sdk/src';

import {
Expand Down Expand Up @@ -158,6 +159,8 @@ describe('spot swap', () => {
);
await makerDriftClient.updateSpotAuctionDuration(0);

await makerDriftClient.updateSpotMarketFuel(0, 1);

[takerDriftClient, takerWSOL, takerUSDC, takerKeypair] =
await createUserWithUSDCAndWSOLAccount(
bankrunContextWrapper,
Expand All @@ -181,6 +184,8 @@ describe('spot swap', () => {
10 * LAMPORTS_PER_SOL
);
await takerDriftClient.deposit(usdcAmount, 0, takerUSDC);

await bankrunContextWrapper.moveTimeForward(FUEL_WINDOW.toNumber());
});

after(async () => {
Expand Down Expand Up @@ -405,6 +410,47 @@ describe('spot swap', () => {
) as UserStatsAccount)
: undefined;

assert(userStatsAccount.fuelDeposits === 2000);

await makerDriftClient.initUserFuel(
await takerDriftClient.getUserAccountPublicKey(),
takerDriftClient.wallet.publicKey,
1000
);
await takerDriftClient.fetchAccounts();
const accountInfo2 = await bankrunContextWrapper.connection.getAccountInfo(
userStatsPublicKey
);
const userStatsAccount2 = accountInfo2
? (takerDriftClient.program.account.user.coder.accounts.decodeUnchecked(
'UserStats',
accountInfo2.data
) as UserStatsAccount)
: undefined;

console.log(userStatsAccount2.fuelDeposits.toString());
assert(userStatsAccount2.fuelDeposits === 3000);

await makerDriftClient.initUserFuel(
await takerDriftClient.getUserAccountPublicKey(),
takerDriftClient.wallet.publicKey,
-2501
);
await takerDriftClient.fetchAccounts();

const accountInfo3 = await bankrunContextWrapper.connection.getAccountInfo(
userStatsPublicKey
);
const userStatsAccount3 = accountInfo3
? (takerDriftClient.program.account.user.coder.accounts.decodeUnchecked(
'UserStats',
accountInfo3.data
) as UserStatsAccount)
: undefined;
console.log(userStatsAccount3.fuelDeposits.toString());

assert(userStatsAccount3.fuelDeposits === 499);

// assert(userStatsAccount.fees.totalFeePaid.eq(new BN(50000)));
assert(userStatsAccount.takerVolume30D.eq(new BN(0)));

Expand Down

0 comments on commit d74ae40

Please sign in to comment.