diff --git a/api/src/sdk.rs b/api/src/sdk.rs index c9a60d3..b620a4d 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -11,11 +11,15 @@ pub fn open(signer: Pubkey, id: u64) -> Instruction { let block_adddress = block_pda(id).0; let market_address = market_pda(id).0; let base_mint_address = mint_pda(id).0; - let collateral_address = get_associated_token_address(&block_adddress, &MINT_ADDRESS); - let commitment_address = get_associated_token_address(&block_adddress, &base_mint_address); + // let collateral_address = get_associated_token_address(&block_adddress, &MINT_ADDRESS); + let collateral_address = collateral_pda(id).0; + // let commitment_address = get_associated_token_address(&block_adddress, &base_mint_address); + let commitment_address = commitment_pda(id).0; let sender_address = get_associated_token_address(&signer, &MINT_ADDRESS); - let vault_base_address = get_associated_token_address(&market_address, &base_mint_address); - let vault_quote_address = get_associated_token_address(&market_address, &MINT_ADDRESS); + // let vault_base_address = get_associated_token_address(&market_address, &base_mint_address); + let vault_base_address = vault_base_pda(id).0; + // let vault_quote_address = get_associated_token_address(&market_address, &MINT_ADDRESS); + let vault_quote_address = vault_quote_pda(id).0; Instruction { program_id: crate::ID, accounts: vec![ diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index 63c3d25..c7eceb8 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -50,6 +50,56 @@ pub fn mint_pda(id: u64) -> (Pubkey, u8) { Pubkey::find_program_address(&[MINT, &id.to_le_bytes()], &crate::ID) } +pub fn collateral_pda(block_id: u64) -> (Pubkey, u8) { + let block_address = block_pda(block_id).0; + Pubkey::find_program_address( + &[ + &block_address.to_bytes(), + &spl_token::ID.to_bytes(), + &MINT_ADDRESS.to_bytes(), + ], + &crate::ID, + ) +} + +pub fn commitment_pda(block_id: u64) -> (Pubkey, u8) { + let block_address = block_pda(block_id).0; + let mint_address = mint_pda(block_id).0; + Pubkey::find_program_address( + &[ + &block_address.to_bytes(), + &spl_token::ID.to_bytes(), + &mint_address.to_bytes(), + ], + &crate::ID, + ) +} + +pub fn vault_base_pda(block_id: u64) -> (Pubkey, u8) { + let market_address = market_pda(block_id).0; + let mint_address = mint_pda(block_id).0; + Pubkey::find_program_address( + &[ + &market_address.to_bytes(), + &spl_token::ID.to_bytes(), + &mint_address.to_bytes(), + ], + &crate::ID, + ) +} + +pub fn vault_quote_pda(block_id: u64) -> (Pubkey, u8) { + let market_address = market_pda(block_id).0; + Pubkey::find_program_address( + &[ + &market_address.to_bytes(), + &spl_token::ID.to_bytes(), + &MINT_ADDRESS.to_bytes(), + ], + &crate::ID, + ) +} + pub fn permit_pda(authority: Pubkey, block_id: u64) -> (Pubkey, u8) { Pubkey::find_program_address( &[PERMIT, &authority.to_bytes(), &block_id.to_le_bytes()], diff --git a/program/src/close.rs b/program/src/close.rs index 12ef4f3..ba2a19a 100644 --- a/program/src/close.rs +++ b/program/src/close.rs @@ -5,7 +5,7 @@ use steel::*; pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. let clock = Clock::get()?; - let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, recipient_info, treasury_info, vault_base_info, vault_quote_info, system_program, token_program] = + let [signer_info, block_info, collateral_info, commitment_info, market_info, mint_base_info, mint_quote_info, recipient_info, treasury_info, vault_base_info, vault_quote_info, system_program, token_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); @@ -14,6 +14,12 @@ pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul let block = block_info .as_account_mut::(&ore_api::ID)? .assert_mut(|b| clock.slot >= b.start_slot + 1500)?; + let _collateral = collateral_info + .is_writable()? + .as_associated_token_account(block_info.key, mint_quote_info.key)?; + let commitment = commitment_info + .is_writable()? + .as_associated_token_account(block_info.key, mint_base_info.key)?; let market = market_info .as_account_mut::(&ore_api::ID)? .assert_mut(|m| m.id == block.id)?; @@ -22,10 +28,12 @@ pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul treasury_info .is_writable()? .has_address(&TREASURY_ADDRESS)?; - let vault_base = - vault_base_info.as_associated_token_account(market_info.key, mint_base_info.key)?; - let vault_quote = - vault_quote_info.as_associated_token_account(market_info.key, mint_quote_info.key)?; + let vault_base = vault_base_info + .is_writable()? + .as_associated_token_account(market_info.key, mint_base_info.key)?; + let vault_quote = vault_quote_info + .is_writable()? + .as_associated_token_account(market_info.key, mint_quote_info.key)?; system_program.is_program(&system_program::ID)?; token_program.is_program(&spl_token::ID)?; @@ -78,6 +86,40 @@ pub fn process_close(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResul &[MARKET, &market.id.to_le_bytes()], )?; + // Burn any remaining commitment. + let commitment_burned = commitment.amount(); + burn_signed( + commitment_info, + mint_base_info, + block_info, + token_program, + commitment_burned, + &[BLOCK, &block.id.to_le_bytes()], + )?; + + // Close token accounts. + close_token_account_signed( + vault_base_info, + signer_info, + market_info, + token_program, + &[MARKET, &market.id.to_le_bytes()], + )?; + close_token_account_signed( + vault_quote_info, + signer_info, + market_info, + token_program, + &[MARKET, &market.id.to_le_bytes()], + )?; + close_token_account_signed( + commitment_info, + signer_info, + block_info, + token_program, + &[BLOCK, &block.id.to_le_bytes()], + )?; + // Close block. block_info.close(signer_info)?; diff --git a/program/src/open.rs b/program/src/open.rs index d013236..0055aaf 100644 --- a/program/src/open.rs +++ b/program/src/open.rs @@ -140,58 +140,171 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Initialize collateral and commitment token accounts. if collateral_info.data_is_empty() { - create_associated_token_account( - signer_info, - block_info, + let collateral_pda = collateral_pda(id); + allocate_account_with_bump( collateral_info, - mint_quote_info, system_program, - token_program, - associated_token_program, + signer_info, + spl_token::state::Account::LEN, + &spl_token::ID, + &[ + block_info.key.as_ref(), + token_program.key.as_ref(), + mint_quote_info.key.as_ref(), + ], + collateral_pda.1, + )?; + solana_program::program::invoke( + &spl_token_2022::instruction::initialize_account3( + &spl_token::ID, + &collateral_pda.0, + &mint_quote_info.key, + &block_info.key, + )?, + &[ + collateral_info.clone(), + mint_quote_info.clone(), + block_info.clone(), + token_program.clone(), + ], )?; } else { - collateral_info.as_associated_token_account(block_info.key, mint_quote_info.key)?; + collateral_info + .has_address(&collateral_pda(id).0)? + .as_token_account()? + .assert(|t| t.mint() == *mint_quote_info.key)? + .assert(|t| t.owner() == *block_info.key)?; } if commitment_info.data_is_empty() { - create_associated_token_account( - signer_info, - block_info, + let commitment_pda = commitment_pda(id); + allocate_account_with_bump( commitment_info, - mint_base_info, system_program, - token_program, - associated_token_program, + signer_info, + spl_token::state::Account::LEN, + &spl_token::ID, + &[ + block_info.key.as_ref(), + token_program.key.as_ref(), + mint_base_info.key.as_ref(), + ], + commitment_pda.1, + )?; + solana_program::program::invoke( + &spl_token_2022::instruction::initialize_account3( + &spl_token::ID, + &commitment_pda.0, + &mint_base_info.key, + &block_info.key, + )?, + &[ + commitment_info.clone(), + mint_base_info.clone(), + block_info.clone(), + token_program.clone(), + ], )?; } else { - commitment_info.as_associated_token_account(block_info.key, mint_base_info.key)?; + // commitment_info.as_associated_token_account(block_info.key, mint_base_info.key)?; + commitment_info + .has_address(&commitment_pda(id).0)? + .as_token_account()? + .assert(|t| t.mint() == *mint_base_info.key)? + .assert(|t| t.owner() == *block_info.key)?; } // Initialize vault token accounts. if vault_base_info.data_is_empty() { - create_associated_token_account( - signer_info, - market_info, + // create_associated_token_account( + // signer_info, + // market_info, + // vault_base_info, + // mint_base_info, + // system_program, + // token_program, + // associated_token_program, + // )?; + let vault_base_pda = vault_base_pda(id); + allocate_account_with_bump( vault_base_info, - mint_base_info, system_program, - token_program, - associated_token_program, + signer_info, + spl_token::state::Account::LEN, + &spl_token::ID, + &[ + market_info.key.as_ref(), + token_program.key.as_ref(), + mint_base_info.key.as_ref(), + ], + vault_base_pda.1, + )?; + solana_program::program::invoke( + &spl_token_2022::instruction::initialize_account3( + &spl_token::ID, + &vault_base_pda.0, + &mint_base_info.key, + &block_info.key, + )?, + &[ + vault_base_info.clone(), + mint_base_info.clone(), + block_info.clone(), + token_program.clone(), + ], )?; } else { - vault_base_info.as_associated_token_account(market_info.key, mint_base_info.key)?; + // vault_base_info.as_associated_token_account(market_info.key, mint_base_info.key)?; + vault_base_info + .has_address(&vault_base_pda(id).0)? + .as_token_account()? + .assert(|t| t.mint() == *mint_base_info.key)? + .assert(|t| t.owner() == *market_info.key)?; } if vault_quote_info.data_is_empty() { - create_associated_token_account( - signer_info, - market_info, + // create_associated_token_account( + // signer_info, + // market_info, + // vault_quote_info, + // mint_quote_info, + // system_program, + // token_program, + // associated_token_program, + // )?; + let vault_quote_pda = vault_quote_pda(id); + allocate_account_with_bump( vault_quote_info, - mint_quote_info, system_program, - token_program, - associated_token_program, + signer_info, + spl_token::state::Account::LEN, + &spl_token::ID, + &[ + market_info.key.as_ref(), + token_program.key.as_ref(), + mint_quote_info.key.as_ref(), + ], + vault_quote_pda.1, + )?; + solana_program::program::invoke( + &spl_token_2022::instruction::initialize_account3( + &spl_token::ID, + &vault_quote_pda.0, + &mint_quote_info.key, + &block_info.key, + )?, + &[ + vault_quote_info.clone(), + mint_quote_info.clone(), + block_info.clone(), + token_program.clone(), + ], )?; } else { - vault_quote_info.as_associated_token_account(market_info.key, mint_quote_info.key)?; + // vault_quote_info.as_associated_token_account(market_info.key, mint_quote_info.key)?; + vault_quote_info + .has_address(&vault_quote_pda(id).0)? + .as_token_account()? + .assert(|t| t.mint() == *mint_quote_info.key)? + .assert(|t| t.owner() == *market_info.key)?; } // Mint hash tokens to market.