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

Permissionless Pool Creation #322

Merged
merged 3 commits into from
Jan 31, 2025
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
10 changes: 6 additions & 4 deletions packages/deepbook/sources/helper/constants.move
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

module deepbook::constants;

const CURRENT_VERSION: u64 = 1; // Update version during upgrades
const POOL_CREATION_FEE: u64 = 0 * 1_000_000; // 0 DEEP
const CURRENT_VERSION: u64 = 2; // Update version during upgrades
const POOL_CREATION_FEE: u64 = 500 * 1_000_000; // 500 DEEP
const FLOAT_SCALING: u64 = 1_000_000_000;
const FLOAT_SCALING_U128: u128 = 1_000_000_000;
const MAX_U64: u64 = ((1u128 << 64) - 1) as u64;
Expand All @@ -18,9 +18,11 @@ const DEEP_UNIT: u64 = 1_000_000;
// Restrictions on limit orders.
// No restriction on the order.
const NO_RESTRICTION: u8 = 0;
// Mandates that whatever amount of an order that can be executed in the current transaction, be filled and then the rest of the order canceled.
// Mandates that whatever amount of an order that can be executed in the current
// transaction, be filled and then the rest of the order canceled.
const IMMEDIATE_OR_CANCEL: u8 = 1;
// Mandates that the entire order size be filled in the current transaction. Otherwise, the order is canceled.
// Mandates that the entire order size be filled in the current transaction.
// Otherwise, the order is canceled.
const FILL_OR_KILL: u8 = 2;
// Mandates that the entire order be passive. Otherwise, cancel the order.
const POST_ONLY: u8 = 3;
Expand Down
48 changes: 43 additions & 5 deletions packages/deepbook/sources/pool.move
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,42 @@ public struct DeepBurned<
deep_burned: u64,
}

// === Public-Mutative Functions * POOL CREATION * ===
/// Create a new pool. The pool is registered in the registry.
/// Checks are performed to ensure the tick size, lot size,
/// and min size are valid.
/// The creation fee is transferred to the treasury address.
/// Returns the id of the pool created
public fun create_permissionless_pool<BaseAsset, QuoteAsset>(
registry: &mut Registry,
tick_size: u64,
lot_size: u64,
min_size: u64,
creation_fee: Coin<DEEP>,
ctx: &mut TxContext,
): ID {
assert!(
creation_fee.value() == constants::pool_creation_fee(),
EInvalidFee,
);
let base_type = type_name::get<BaseAsset>();
let quote_type = type_name::get<QuoteAsset>();
let whitelisted_pool = false;
let stable_pool =
registry.is_stablecoin(base_type) && registry.is_stablecoin(quote_type);

create_pool<BaseAsset, QuoteAsset>(
registry,
tick_size,
lot_size,
min_size,
creation_fee,
whitelisted_pool,
stable_pool,
ctx,
)
}

// === Public-Mutative Functions * EXCHANGE * ===
/// Place a limit order. Quantity is in base asset terms.
/// For current version pay_with_deep must be true, so the fee will be paid with
Expand Down Expand Up @@ -661,7 +697,6 @@ public fun burn_deep<BaseAsset, QuoteAsset>(
/// Create a new pool. The pool is registered in the registry.
/// Checks are performed to ensure the tick size, lot size, and min size are
/// valid.
/// The creation fee is transferred to the treasury address.
/// Returns the id of the pool created
public fun create_pool_admin<BaseAsset, QuoteAsset>(
registry: &mut Registry,
Expand Down Expand Up @@ -769,6 +804,13 @@ public fun whitelisted<BaseAsset, QuoteAsset>(
self.load_inner().state.governance().whitelisted()
}

/// Accessor to check if the pool is a stablecoin pool.
public fun stable_pool<BaseAsset, QuoteAsset>(
self: &Pool<BaseAsset, QuoteAsset>,
): bool {
self.load_inner().state.governance().stable()
}

public fun registered_pool<BaseAsset, QuoteAsset>(
self: &Pool<BaseAsset, QuoteAsset>,
): bool {
Expand Down Expand Up @@ -1070,10 +1112,6 @@ public(package) fun create_pool<BaseAsset, QuoteAsset>(
stable_pool: bool,
ctx: &mut TxContext,
): ID {
assert!(
creation_fee.value() == constants::pool_creation_fee(),
EInvalidFee,
);
assert!(tick_size > 0, EInvalidTickSize);
assert!(math::is_power_of_ten(tick_size), EInvalidTickSize);
assert!(lot_size > 0, EInvalidLotSize);
Expand Down
80 changes: 79 additions & 1 deletion packages/deepbook/sources/registry.move
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module deepbook::registry;
use deepbook::constants;
use std::type_name::{Self, TypeName};
use sui::bag::{Self, Bag};
use sui::dynamic_field;
use sui::vec_set::{Self, VecSet};
use sui::versioned::{Self, Versioned};

Expand All @@ -17,6 +18,8 @@ const EPackageVersionNotEnabled: u64 = 3;
const EVersionNotEnabled: u64 = 4;
const EVersionAlreadyEnabled: u64 = 5;
const ECannotDisableCurrentVersion: u64 = 6;
const ECoinAlreadyWhitelisted: u64 = 7;
const ECoinNotWhitelisted: u64 = 8;

public struct REGISTRY has drop {}

Expand All @@ -42,6 +45,8 @@ public struct PoolKey has copy, drop, store {
quote: TypeName,
}

public struct StableCoinKey has store, copy, drop {}

fun init(_: REGISTRY, ctx: &mut TxContext) {
let registry_inner = RegistryInner {
allowed_versions: vec_set::singleton(constants::current_version()),
Expand Down Expand Up @@ -103,6 +108,78 @@ public fun disable_version(
self.allowed_versions.remove(&version);
}

/// Adds a stablecoin to the whitelist
/// Only Admin can add stablecoin
public fun add_stablecoin<StableCoin>(
self: &mut Registry,
_cap: &DeepbookAdminCap,
) {
let _: &mut RegistryInner = self.load_inner_mut();
let stable_type = type_name::get<StableCoin>();
if (
!dynamic_field::exists_(
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of adding each stablecoin as a new dynamic field, what if we initialized a new Bag as a df and just added/removed from this bag? We can't change the registry struct, but this would standardize adding a stablecoin with adding a pool key

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently it's only one dynamic field stablecoinkey with the value as a vecset. Since there's no balance needed here like the balance manager, I think vecset will be better? Another idea is changing value into bag, and we can potentially resolve our vSUI/SUI stable problem (each asset added can correspond to a "base asset" like usdc or sui)

&self.id,
StableCoinKey {},
)
) {
dynamic_field::add(
&mut self.id,
StableCoinKey {},
vec_set::singleton(stable_type),
);
} else {
let stable_coins: &mut VecSet<TypeName> = dynamic_field::borrow_mut(
&mut self.id,
StableCoinKey {},
);
assert!(!stable_coins.contains(&stable_type), ECoinAlreadyWhitelisted);
stable_coins.insert(stable_type);
};
}

/// Removes a stablecoin from the whitelist
/// Only Admin can remove stablecoin
public fun remove_stablecoin<StableCoin>(
self: &mut Registry,
_cap: &DeepbookAdminCap,
) {
let _: &mut RegistryInner = self.load_inner_mut();
let stable_type = type_name::get<StableCoin>();
assert!(
dynamic_field::exists_(
&self.id,
StableCoinKey {},
),
ECoinNotWhitelisted,
);
let stable_coins: &mut VecSet<TypeName> = dynamic_field::borrow_mut(
&mut self.id,
StableCoinKey {},
);
assert!(stable_coins.contains(&stable_type), ECoinNotWhitelisted);
stable_coins.remove(&stable_type);
}

/// Returns whether the given coin is whitelisted
public fun is_stablecoin(self: &Registry, stable_type: TypeName): bool {
let _: &RegistryInner = self.load_inner();
if (
!dynamic_field::exists_(
&self.id,
StableCoinKey {},
)
) {
false
} else {
let stable_coins: &VecSet<TypeName> = dynamic_field::borrow(
&self.id,
StableCoinKey {},
);

stable_coins.contains(&stable_type)
}
}

// === Public-Package Functions ===
public(package) fun load_inner_mut(self: &mut Registry): &mut RegistryInner {
let inner: &mut RegistryInner = self.inner.load_value_mut();
Expand All @@ -116,7 +193,8 @@ public(package) fun load_inner_mut(self: &mut Registry): &mut RegistryInner {
}

/// Register a new pool in the registry.
/// Asserts if (Base, Quote) pool already exists or (Quote, Base) pool already exists.
/// Asserts if (Base, Quote) pool already exists or
/// (Quote, Base) pool already exists.
public(package) fun register_pool<BaseAsset, QuoteAsset>(
self: &mut Registry,
pool_id: ID,
Expand Down
9 changes: 4 additions & 5 deletions packages/deepbook/sources/state/governance.move
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ public(package) fun whitelisted(self: &Governance): bool {
self.whitelisted
}

public(package) fun stable(self: &Governance): bool {
self.stable
}

public(package) fun quorum(self: &Governance): u64 {
self.quorum
}
Expand Down Expand Up @@ -312,11 +316,6 @@ public fun voting_power(self: &Governance): u64 {
self.voting_power
}

#[test_only]
public fun stable(self: &Governance): bool {
self.stable
}

#[test_only]
public fun proposals(self: &Governance): VecMap<ID, Proposal> {
self.proposals
Expand Down
Loading