Skip to content

Commit

Permalink
[T22] Libreplex royalty enforcement support (#91)
Browse files Browse the repository at this point in the history
* [mmm] Add additional accounts for royalty enforcement

* [T22] Add libreplex royalty enforcement support

* remove unnecessary comment

* add sdk integration

* make creator writable

* use args

* init mint outside of provider

* reduce CU

* remove unused sys account

* address comments
  • Loading branch information
solonk8 authored Apr 17, 2024
1 parent 53bd82e commit bda2e77
Show file tree
Hide file tree
Showing 18 changed files with 2,605 additions and 191 deletions.
6 changes: 6 additions & 0 deletions Anchor.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ address = "ocp4vWUzA2z2XMYJ3QhM9vWdyoyoQwAFJhRdVTbvo9E" # ocp: open_creator_prot
[[test.validator.clone]]
address = "6Huqrb4xxmmNA4NufYdgpmspoLmjXFd3qEfteCddLgSz" # ocp: policy (allow all)

[[test.validator.clone]]
address = "99jtJwGDfaBKXtc7kxQneAGbERGK8F5XyJWHv7qTbj9G" # global deny list for libreplex royalty enforcement

[[test.validator.clone]]
address = "CZ1rQoAHSqWBoAEfqGsiLhgbM59dDrCWk3rnG5FXaoRV" # libreplex royalty enforcement

[[test.genesis]]
address = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
program = "./tests/deps/spl_token_2022.so"
Expand Down
3 changes: 3 additions & 0 deletions programs/mmm/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,6 @@ pub const MPL_TOKEN_AUTH_RULES: Pubkey = pubkey!("auth9SigNpDKz4sJJ1DfCTuZrZNSAg
pub const M2_PROGRAM: Pubkey = pubkey!("M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K");
pub const M2_PREFIX: &str = "m2";
pub const M2_AUCTION_HOUSE: Pubkey = pubkey!("E8cU1WiRWjanGxmn96ewBgk9vPTcL6AEZ1t6F6fkgUWe");

pub const LIBREPLEX_ROYALTY_ENFORCEMENT_PROGRAM_ID: Pubkey =
pubkey!("CZ1rQoAHSqWBoAEfqGsiLhgbM59dDrCWk3rnG5FXaoRV");
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ pub struct ExtWithdrawSell<'info> {
pub associated_token_program: Program<'info, AssociatedToken>,
}

pub fn handler(ctx: Context<ExtWithdrawSell>, args: WithdrawSellArgs) -> Result<()> {
pub fn handler<'info>(
ctx: Context<'_, '_, '_, 'info, ExtWithdrawSell<'info>>,
args: WithdrawSellArgs,
) -> Result<()> {
let owner = &ctx.accounts.owner;
let asset_token_account = &ctx.accounts.asset_token_account;
let sellside_escrow_token_account = &ctx.accounts.sellside_escrow_token_account;
Expand Down Expand Up @@ -101,7 +104,7 @@ pub fn handler(ctx: Context<ExtWithdrawSell>, args: WithdrawSellArgs) -> Result<
asset_mint.to_account_info(),
asset_token_account.to_account_info(),
pool.to_account_info(),
&[], // additional_accounts
ctx.remaining_accounts,
args.asset_amount,
0, // decimals
pool_seeds,
Expand Down
56 changes: 44 additions & 12 deletions programs/mmm/src/instructions/ext_vanilla/sol_ext_fulfill_buy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ use crate::{
constants::*,
errors::MMMErrorCode,
index_ra,
instructions::{check_remaining_accounts_for_m2, log_pool, try_close_pool, withdraw_m2},
instructions::{
check_remaining_accounts_for_m2, get_transfer_hook_program_id, log_pool,
pay_creator_fees_in_sol_ext, split_remaining_account_for_ext, try_close_pool, withdraw_m2,
},
state::{Pool, SellState},
util::{
assert_valid_fees_bp, check_allowlists_for_mint_ext, get_buyside_seller_receives,
Expand Down Expand Up @@ -126,6 +129,16 @@ pub fn handler<'info>(
&[ctx.bumps.buyside_sol_escrow_account],
]];
let remaining_accounts = ctx.remaining_accounts;
if pool.using_shared_escrow() {
check_remaining_accounts_for_m2(remaining_accounts, &pool.owner.key())?;
}

let (optional_creator_account, remaining_account_without_m2, sfbp) =
split_remaining_account_for_ext(
remaining_accounts,
&asset_mint.to_account_info(),
pool.using_shared_escrow(),
)?;

check_allowlists_for_mint_ext(
&pool.allowlists,
Expand All @@ -141,8 +154,8 @@ pub fn handler<'info>(
get_buyside_seller_receives(
total_price,
lp_fee_bp,
0, // metadata_royalty_bp
0, // buyside_creator_royalty_bp,
sfbp, // royalty_bp
10_000,
)
}?;

Expand All @@ -160,9 +173,7 @@ pub fn handler<'info>(
let lp_fee = get_sol_lp_fee(pool, buyside_sol_escrow_account.lamports(), seller_receives)?;

// withdraw sol from M2 first if shared escrow is enabled
let remaining_account_without_m2 = if pool.using_shared_escrow() {
check_remaining_accounts_for_m2(remaining_accounts, &pool.owner.key())?;

if pool.using_shared_escrow() {
let amount: u64 = (total_price as i64 + maker_fee) as u64;
withdraw_m2(
pool,
Expand All @@ -178,10 +189,7 @@ pub fn handler<'info>(
.shared_escrow_count
.checked_sub(args.asset_amount)
.ok_or(MMMErrorCode::NumericOverflow)?;
&remaining_accounts[2..]
} else {
remaining_accounts
};
}

if pool.reinvest_fulfill_buy {
if pool.using_shared_escrow() {
Expand Down Expand Up @@ -261,13 +269,32 @@ pub fn handler<'info>(
))?;
}

let royalty_paid: u64 = if let Ok(transfer_hook_program_id) =
get_transfer_hook_program_id(&asset_mint.to_account_info())
{
if transfer_hook_program_id == Some(LIBREPLEX_ROYALTY_ENFORCEMENT_PROGRAM_ID) {
pay_creator_fees_in_sol_ext(
seller_receives,
optional_creator_account,
buyside_sol_escrow_account.to_account_info(),
sfbp,
buyside_sol_escrow_account_seeds,
)?
} else {
0
}
} else {
0
};

// prevent frontrun by pool config changes
let payment_amount = total_price
.checked_sub(lp_fee)
.ok_or(MMMErrorCode::NumericOverflow)?
.checked_sub(taker_fee as u64)
.ok_or(MMMErrorCode::NumericOverflow)?
.checked_sub(royalty_paid)
.ok_or(MMMErrorCode::NumericOverflow)?;

if payment_amount < args.min_payment_amount {
return Err(MMMErrorCode::InvalidRequestedPrice.into());
}
Expand Down Expand Up @@ -353,7 +380,12 @@ pub fn handler<'info>(
log_pool("post_ext_sol_fulfill_buy", pool)?;
try_close_pool(pool, owner.to_account_info())?;

msg!("{{\"lp_fee\":{},\"total_price\":{}}}", lp_fee, total_price,);
msg!(
"{{\"lp_fee\":{},\"total_price\":{},\"royalty_paid\":{}}}",
lp_fee,
total_price,
royalty_paid,
);

Ok(())
}
37 changes: 33 additions & 4 deletions programs/mmm/src/instructions/ext_vanilla/sol_ext_fulfill_sell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ use crate::{
constants::*,
errors::MMMErrorCode,
instructions::{
get_sell_fulfill_pool_price_info, log_pool, try_close_pool, try_close_sell_state,
PoolPriceInfo,
get_sell_fulfill_pool_price_info, get_transfer_hook_program_id, log_pool,
pay_creator_fees_in_sol_ext, split_remaining_account_for_ext, try_close_pool,
try_close_sell_state, PoolPriceInfo,
},
state::{Pool, SellState},
util::check_allowlists_for_mint_ext,
Expand Down Expand Up @@ -106,6 +107,9 @@ pub fn handler<'info>(
let payer = &ctx.accounts.payer;
let payer_asset_account = &ctx.accounts.payer_asset_account;
let asset_mint = &ctx.accounts.asset_mint;
let remaining_accounts = ctx.remaining_accounts;
let (optional_creator_account, remaining_account_without_creator, sfbp) =
split_remaining_account_for_ext(remaining_accounts, &asset_mint.to_account_info(), false)?;

let sellside_escrow_token_account = &ctx.accounts.sellside_escrow_token_account;
let buyside_sol_escrow_account = &ctx.accounts.buyside_sol_escrow_account;
Expand Down Expand Up @@ -165,7 +169,7 @@ pub fn handler<'info>(
asset_mint.to_account_info(),
payer_asset_account.to_account_info(),
pool.to_account_info(),
&[],
remaining_account_without_creator,
args.asset_amount,
0,
pool_seeds,
Expand Down Expand Up @@ -216,11 +220,31 @@ pub fn handler<'info>(
.checked_add(lp_fee)
.ok_or(MMMErrorCode::NumericOverflow)?;

let royalty_paid: u64 = if let Ok(transfer_hook_program_id) =
get_transfer_hook_program_id(&asset_mint.to_account_info())
{
if transfer_hook_program_id == Some(LIBREPLEX_ROYALTY_ENFORCEMENT_PROGRAM_ID) {
pay_creator_fees_in_sol_ext(
total_price,
optional_creator_account,
payer.to_account_info(),
sfbp,
&[&[&[]]],
)?
} else {
0
}
} else {
0
};

// prevent frontrun by pool config changes
let payment_amount = total_price
.checked_add(lp_fee)
.ok_or(MMMErrorCode::NumericOverflow)?
.checked_add(taker_fee as u64)
.ok_or(MMMErrorCode::NumericOverflow)?
.checked_add(royalty_paid)
.ok_or(MMMErrorCode::NumericOverflow)?;
if payment_amount > args.max_payment_amount {
return Err(MMMErrorCode::InvalidRequestedPrice.into());
Expand All @@ -236,7 +260,12 @@ pub fn handler<'info>(
log_pool("post_ext_sol_fulfill_sell", pool)?;
try_close_pool(pool, owner.to_account_info())?;

msg!("{{\"lp_fee\":{},\"total_price\":{}}}", lp_fee, total_price);
msg!(
"{{\"lp_fee\":{},\"total_price\":{},\"royalty_paid\":{}}}",
lp_fee,
total_price,
royalty_paid,
);

Ok(())
}
5 changes: 4 additions & 1 deletion programs/mmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,10 @@ pub mod mmm {
instructions::sol_ext_fulfill_buy::handler(ctx, args)
}

pub fn ext_withdraw_sell(ctx: Context<ExtWithdrawSell>, args: WithdrawSellArgs) -> Result<()> {
pub fn ext_withdraw_sell<'info>(
ctx: Context<'_, '_, '_, 'info, ExtWithdrawSell<'info>>,
args: WithdrawSellArgs,
) -> Result<()> {
instructions::ext_withdraw_sell::handler(ctx, args)
}
}
Loading

0 comments on commit bda2e77

Please sign in to comment.