Skip to content

Commit

Permalink
[mmm] deposit sell for T22 extension
Browse files Browse the repository at this point in the history
  • Loading branch information
solonk8 committed Mar 6, 2024
1 parent f662f67 commit dcaaa5d
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 13 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions programs/mmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ community-managed-token = { version = "0.3.1", features = ["no-entrypoint"] }
mpl-token-metadata = { version = "4.0.0" }
open_creator_protocol = { version = "0.4.2", features = ["cpi"] }
solana-program = "~1.17"
spl-token-group-interface = "0.1.0"
spl-token = { version = "4.0.0", features = ["no-entrypoint"] }
spl-associated-token-account = { version = "2.2.0", features = [
"no-entrypoint",
Expand Down
2 changes: 2 additions & 0 deletions programs/mmm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ pub enum MMMErrorCode {
UnexpectedMetadataUri, // 0x178c
#[msg("Invalid remaining accounts")]
InvalidRemainingAccounts, // 0x178d
#[msg("Invalid token extensions")]
InValidTokenExtension, // 0x178e
}
40 changes: 37 additions & 3 deletions programs/mmm/src/ext_util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
use solana_program::{account_info::AccountInfo, pubkey::Pubkey};
use spl_token_client
use spl_token_2022::{
extension::{
group_member_pointer::GroupMemberPointer, BaseStateWithExtensions, StateWithExtensions,
},
state::Mint as Token22Mint,
};
use spl_token_group_interface::state::TokenGroupMember;

use crate::state::{Allowlist, ALLOWLIST_KIND_GROUP};

use {crate::errors::MMMErrorCode, anchor_lang::prelude::*};

pub fn check_group_ext_for_mint(token_mint: &AccountInfo, allowlists: &[Allowlist]) -> Result<()> {
if token_mint.data_is_empty() {
return Err(MMMErrorCode::InvalidTokenMint.into());
}
let borrowed_data = token_mint.data.borrow();
let mint_deserialized = StateWithExtensions::<Token22Mint>::unpack(&borrowed_data)?;
if !mint_deserialized.base.is_initialized {
return Err(MMMErrorCode::InvalidTokenMint.into());
}
if let Ok(group_member_ptr) = mint_deserialized.get_extension::<GroupMemberPointer>() {
if Some(*token_mint.key) != Option::<Pubkey>::from(group_member_ptr.member_address) {
return Err(MMMErrorCode::InValidTokenExtension.into());
}
}
if let Ok(group_member) = mint_deserialized.get_extension::<TokenGroupMember>() {
let group_address = allowlists
.iter()
.find(|allowlist| allowlist.kind == ALLOWLIST_KIND_GROUP)
.map(|allowlist| allowlist.value);
if Some(group_member.group) != group_address {
return Err(MMMErrorCode::InValidTokenExtension.into());
}
} else {
return Err(MMMErrorCode::InValidTokenExtension.into());
}

pub fn check_group_for_mint(mint_state: &AccountInfo, group_address: Pubkey) -> Result<()> {

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ use anchor_spl::{
associated_token::AssociatedToken,
token_interface::{Mint, TokenAccount, TokenInterface},
};
use solana_program::program::invoke;
use spl_token_2022::onchain::invoke_transfer_checked;

use crate::{
constants::*,
errors::MMMErrorCode,
ext_util::check_group_ext_for_mint,
state::{Pool, SellState},
util::{check_allowlists_for_mint, log_pool},
util::log_pool,
};

#[derive(AnchorSerialize, AnchorDeserialize)]
Expand Down Expand Up @@ -44,7 +47,6 @@ pub struct ExtDepositeSell<'info> {
associated_token::mint = asset_mint,
associated_token::authority = pool,
associated_token::token_program = token_program,
)]
pub sellside_escrow_token_account: Box<InterfaceAccount<'info, TokenAccount>>,
#[account(
Expand All @@ -65,7 +67,10 @@ pub struct ExtDepositeSell<'info> {
pub rent: Sysvar<'info, Rent>,
}

pub fn handler(ctx: Context<ExtDepositeSell>, args: ExtDepositeSellArgs) -> Result<()> {
pub fn handler<'info>(
ctx: Context<'_, '_, '_, 'info, ExtDepositeSell<'info>>,
args: ExtDepositeSellArgs,
) -> Result<()> {
let owner = &ctx.accounts.owner;
let asset_token_account = &ctx.accounts.asset_token_account;
let asset_mint = &ctx.accounts.asset_mint;
Expand All @@ -75,11 +80,52 @@ pub fn handler(ctx: Context<ExtDepositeSell>, args: ExtDepositeSellArgs) -> Resu
let sell_state = &mut ctx.accounts.sell_state;

if pool.using_shared_escrow() {
return Err(MMMErrorCode::InvalidPool.into());
return Err(MMMErrorCode::InvalidAccountState.into());
}

// check group/membership to determine
// the added token belongs to the pool group
check_group_ext_for_mint(&asset_mint.to_account_info(), &pool.allowlists)?;
invoke_transfer_checked(
token_program.key,
asset_token_account.to_account_info(),
asset_mint.to_account_info(),
sellside_escrow_token_account.to_account_info(),
owner.to_account_info(),
ctx.remaining_accounts,
args.asset_amount,
0,
&[],
)?;

if asset_token_account.amount == args.asset_amount {
invoke(
&spl_token_2022::instruction::close_account(
token_program.key,
&asset_token_account.key(),
&owner.key(),
&owner.key(),
&[],
)?,
&[
asset_token_account.to_account_info(),
owner.to_account_info(),
],
)?;
}

pool.sellside_asset_amount = pool
.sellside_asset_amount
.checked_add(args.asset_amount)
.ok_or(MMMErrorCode::NumericOverflow)?;

sell_state.pool = pool.key();
sell_state.pool_owner = owner.key();
sell_state.asset_mint = asset_mint.key();
sell_state.cosigner_annotation = pool.cosigner_annotation;
sell_state.asset_amount = sell_state
.asset_amount
.checked_add(args.asset_amount)
.ok_or(MMMErrorCode::NumericOverflow)?;
log_pool("post_deposit_sell", pool)?;

Ok(())
}
4 changes: 2 additions & 2 deletions programs/mmm/src/instructions/ext_vanilla/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod ext_sol_deposit_sell;
pub mod ext_deposit_sell;

pub use ext_sol_deposit_sell::*;
pub use ext_deposit_sell::*;
6 changes: 4 additions & 2 deletions programs/mmm/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub const ALLOWLIST_KIND_FVCA: u8 = 1;
pub const ALLOWLIST_KIND_MINT: u8 = 2;
pub const ALLOWLIST_KIND_MCC: u8 = 3;
pub const ALLOWLIST_KIND_METADATA: u8 = 4;
pub const ALLOWLIST_KIND_GROUP: u8 = 5;
// ANY nft will pass the allowlist check, please make sure to use cosigner to check NFT validity
pub const ALLOWLIST_KIND_ANY: u8 = u8::MAX;

Expand All @@ -25,10 +26,11 @@ impl Allowlist {
// kind == 2: single mint, useful for SFT
// kind == 3: verified MCC
// kind == 4: metadata
// kind == 5,6,... will be supported in the future
// kind == 5: group extension
// kind == 6,7,... will be supported in the future
// kind == 255: any
pub fn valid(&self) -> bool {
if self.kind > ALLOWLIST_KIND_METADATA && self.kind != ALLOWLIST_KIND_ANY {
if self.kind > ALLOWLIST_KIND_GROUP && self.kind != ALLOWLIST_KIND_ANY {
return false;
}
if self.kind != 0 && self.kind != ALLOWLIST_KIND_ANY {
Expand Down
24 changes: 24 additions & 0 deletions sdk/src/idl/mmm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,18 @@ export type Mmm = {
]
}
},
{
"name": "ExtDepositeSellArgs",
"type": {
"kind": "struct",
"fields": [
{
"name": "assetAmount",
"type": "u64"
}
]
}
},
{
"name": "SolMip1FulfillSellArgs",
"type": {
Expand Down Expand Up @@ -4155,6 +4167,18 @@ export const IDL: Mmm = {
]
}
},
{
"name": "ExtDepositeSellArgs",
"type": {
"kind": "struct",
"fields": [
{
"name": "assetAmount",
"type": "u64"
}
]
}
},
{
"name": "SolMip1FulfillSellArgs",
"type": {
Expand Down

0 comments on commit dcaaa5d

Please sign in to comment.