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

revoke whitelist logic #188

Merged
merged 7 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
2 changes: 1 addition & 1 deletion psyoptions-american-instrument/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@convergence-rfq/psyoptions-american-instrument",
"version": "2.3.2",
"version": "2.3.3",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand Down
2 changes: 1 addition & 1 deletion psyoptions-european-instrument/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@convergence-rfq/psyoptions-european-instrument",
"version": "2.3.2",
"version": "2.3.3",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand Down
2 changes: 1 addition & 1 deletion rfq/js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@convergence-rfq/rfq",
"version": "2.3.2",
"version": "2.3.3",
"license": "MIT",
"publishConfig": {
"access": "public",
Expand Down
22 changes: 13 additions & 9 deletions rfq/program/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,20 +114,24 @@ pub enum ProtocolError {
DefaultValueIsNotPermitted,
#[msg("Specified oracle source is missing")]
OracleSourceIsMissing,
#[msg("Address Already Exists on Whitelist")]
AddressAlreadyExistsOnWhitelist,
#[msg("Whitelist Maximum Capacity Reached")]
#[msg("Whitelist maximum capacity reached")]
WhitelistMaximumCapacityReached,
#[msg("Cannot Respond as Maker Address not Whitelisted")]
#[msg("Cannot respond as maker address is not whitelisted")]
MakerAddressNotWhitelisted,
#[msg("Whitelist Creator Mismatch")]
#[msg("Whitelist creator mismatch")]
WhitelistCreatorMismatch,
#[msg("Whitelist Empty")]
#[msg("Whitelist empty")]
WhitelistEmpty,
#[msg("Address Does not Exist on Whitelist")]
#[msg("Address does not exist on whitelist")]
AddressDoesNotExistOnWhitelist,
#[msg("Whitelist Not Provided")]
#[msg("Whitelist not provided")]
WhitelistNotProvided,
#[msg("Whitelist Address Mismatch")]
#[msg("Whitelist address mismatch")]
WhitelistAddressMismatch,
#[msg("Whitelist already associated with an RFQ")]
WhitelistAlreadyAssociated,
#[msg("Whitelist has an associated RFQ")]
WhitelistHasAssociatedRfq,
#[msg("Whitelist RFQ association mismatch")]
WhitelistAssocaitionRFQMismatch,
}
24 changes: 22 additions & 2 deletions rfq/program/src/instructions/rfq/clean_up_rfq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::{
errors::ProtocolError,
seeds::PROTOCOL_SEED,
state::{ProtocolState, Rfq, RfqState},
whitelist::Whitelist,
};
use anchor_lang::prelude::*;

Expand All @@ -15,6 +16,8 @@ pub struct CleanUpRfqAccounts<'info> {
pub protocol: Box<Account<'info, ProtocolState>>,
#[account(mut, close = taker)]
pub rfq: Box<Account<'info, Rfq>>,
#[account(mut)]
pub whitelist: Option<Box<Account<'info, Whitelist>>>,
}

fn validate(ctx: &Context<CleanUpRfqAccounts>) -> Result<()> {
Expand Down Expand Up @@ -42,6 +45,23 @@ fn validate(ctx: &Context<CleanUpRfqAccounts>) -> Result<()> {

pub fn clean_up_rfq_instruction(ctx: Context<CleanUpRfqAccounts>) -> Result<()> {
validate(&ctx)?;

Ok(())
let CleanUpRfqAccounts {
whitelist,
rfq,
taker,
..
} = &ctx.accounts;
match whitelist {
Some(whitelist) => {
require_keys_eq!(
whitelist.associated_rfq,
rfq.key(),
ProtocolError::WhitelistAssocaitionRFQMismatch
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can accidentally pass a None case if the rfq address exists and it wouldn't be cleaned up

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it makes sense to reuse the logic of "check whitelist account passed" used in response to rfq

Copy link
Contributor Author

Choose a reason for hiding this comment

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

resolved

whitelist.close(taker.to_account_info())
}
None => {
return Ok(());
}
}
}
37 changes: 31 additions & 6 deletions rfq/program/src/instructions/rfq/create_rfq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
interfaces::instrument::validate_quote_instrument_data,
seeds::{PROTOCOL_SEED, RFQ_SEED},
state::{rfq::QuoteAsset, ApiLeg, FixedSize, OrderType, ProtocolState, Rfq, StoredRfqState},
whitelist::Whitelist,
};
use anchor_lang::prelude::*;
use solana_program::hash::hash;
Expand Down Expand Up @@ -48,6 +49,8 @@ pub struct CreateRfqAccounts<'info> {
bump
)]
pub rfq: Box<Account<'info, Rfq>>,
#[account(mut)]
pub whitelist: Option<Box<Account<'info, Whitelist>>>,

pub system_program: Program<'info, System>,
}
Expand Down Expand Up @@ -102,6 +105,20 @@ fn validate_recent_timestamp(recent_timestamp: u64) -> Result<()> {
Ok(())
}

fn validate_whitelist(whitelist: &Whitelist, creator: Pubkey) -> Result<()> {
require_keys_eq!(
whitelist.associated_rfq,
Pubkey::default(),
ProtocolError::WhitelistAlreadyAssociated
);
require_keys_eq!(
whitelist.creator,
creator,
ProtocolError::WhitelistCreatorMismatch
);
Ok(())
}

#[allow(clippy::too_many_arguments)]
pub fn create_rfq_instruction<'info>(
ctx: Context<'_, '_, '_, 'info, CreateRfqAccounts<'info>>,
Expand All @@ -114,18 +131,26 @@ pub fn create_rfq_instruction<'info>(
active_window: u32,
settling_window: u32,
recent_timestamp: u64,
whitelist: Option<Pubkey>,
) -> Result<()> {
let protocol = &ctx.accounts.protocol;
let mut remaining_accounts = ctx.remaining_accounts.iter();
validate_quote(protocol, &mut remaining_accounts, &quote_asset)?;
validate_legs(protocol, &mut remaining_accounts, expected_legs_size, &legs)?;
validate_recent_timestamp(recent_timestamp)?;

let CreateRfqAccounts { taker, rfq, .. } = ctx.accounts;
let whitelist_to_pass = match whitelist {
Some(whitelist) => whitelist,
None => Pubkey::default(),
let CreateRfqAccounts {
taker,
rfq,
whitelist,
..
} = ctx.accounts;
let whitelist_to_pass: Pubkey;
match whitelist {
Some(whitelist) => {
validate_whitelist(whitelist, taker.key())?;
whitelist.associated_rfq = rfq.key();
whitelist_to_pass = whitelist.key()
}
None => whitelist_to_pass = Pubkey::default(),
};

rfq.set_inner(Rfq {
Expand Down
5 changes: 5 additions & 0 deletions rfq/program/src/instructions/rfq/respond_to_rfq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ fn validate(
whitelist.key(),
ProtocolError::WhitelistAddressMismatch
);
require_keys_eq!(
whitelist.associated_rfq,
rfq.key(),
ProtocolError::WhitelistAssocaitionRFQMismatch
);
require!(
whitelist.is_whitelisted(maker.key),
ProtocolError::MakerAddressNotWhitelisted
Expand Down
37 changes: 0 additions & 37 deletions rfq/program/src/instructions/whitelist/add_address_to_whitelist.rs

This file was deleted.

7 changes: 7 additions & 0 deletions rfq/program/src/instructions/whitelist/cleanup_whitelist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,12 @@ pub struct CleanUpWhitelistAccounts<'info> {
}

pub fn clean_up_whitelist_instruction(_ctx: Context<CleanUpWhitelistAccounts>) -> Result<()> {
let CleanUpWhitelistAccounts {
whitelist_account, ..
} = _ctx.accounts;
require!(
whitelist_account.associated_rfq == Pubkey::default(),
ProtocolError::WhitelistHasAssociatedRfq
);
Ok(())
}
23 changes: 8 additions & 15 deletions rfq/program/src/instructions/whitelist/create_whitelist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::mem;

#[derive(Accounts)]
#[instruction(
expected_whitelist_size: u16
length: u8
)]
pub struct CreateWhitelistAccounts<'info> {
#[account(
init_if_needed,
payer = creator,
space = 8 + mem::size_of::<Whitelist>() + (expected_whitelist_size as usize)
space = get_whitelist_size_from_length(length),
)]
pub whitelist_account: Box<Account<'info, Whitelist>>,
#[account(mut)]
Expand All @@ -20,11 +20,9 @@ pub struct CreateWhitelistAccounts<'info> {

pub fn create_whitelist_instruction(
ctx: Context<CreateWhitelistAccounts>,
expected_whitelist_size: u16,
whitelist_to_add: Vec<Pubkey>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you're passing it in one ix, you already have a length in this vector, no need to pass it as a parameter

Copy link
Contributor Author

Choose a reason for hiding this comment

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

resolved

) -> Result<()> {
let expected_whitelist_capacity = calculate_expected_capacity(expected_whitelist_size);
validate_whitelist_inputs(expected_whitelist_capacity, &whitelist_to_add)?;
validate_whitelist_inputs(whitelist_to_add.len())?;
let CreateWhitelistAccounts {
creator,
whitelist_account,
Expand All @@ -33,26 +31,21 @@ pub fn create_whitelist_instruction(

whitelist_account.set_inner(Whitelist {
creator: creator.key(),
associated_rfq: Pubkey::default(),
whitelist: whitelist_to_add,
capacity: expected_whitelist_capacity,
});

Ok(())
}

fn validate_whitelist_inputs(
expected_whitelist_capacity: u8,
whitelist_to_add: &Vec<Pubkey>,
) -> Result<()> {
fn validate_whitelist_inputs(length: usize) -> Result<()> {
require!(
whitelist_to_add.len() <= (expected_whitelist_capacity as usize),
length <= Whitelist::MAX_WHITELIST_SIZE as usize,
ProtocolError::WhitelistMaximumCapacityReached
);

Ok(())
}

fn calculate_expected_capacity(expected_whitelist_size: u16) -> u8 {
let pubkey_size = 32;
(expected_whitelist_size / pubkey_size) as u8
fn get_whitelist_size_from_length(length: u8) -> usize {
8 + mem::size_of::<Whitelist>() + length as usize * 32
}
2 changes: 0 additions & 2 deletions rfq/program/src/instructions/whitelist/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
pub mod add_address_to_whitelist;
pub mod cleanup_whitelist;
pub mod create_whitelist;
pub mod remove_address_from_whitelist;

This file was deleted.

21 changes: 1 addition & 20 deletions rfq/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,8 @@ use instructions::rfq::settle_one_party_default::*;
use instructions::rfq::settle_two_party_default::*;
use instructions::rfq::unlock_response_collateral::*;
use instructions::rfq::unlock_rfq_collateral::*;
use instructions::whitelist::add_address_to_whitelist::*;
use instructions::whitelist::cleanup_whitelist::*;
use instructions::whitelist::create_whitelist::*;
use instructions::whitelist::remove_address_from_whitelist::*;
use state::*;

security_txt! {
Expand Down Expand Up @@ -188,7 +186,6 @@ pub mod rfq {
active_window: u32,
settling_window: u32,
recent_timestamp: u64, // used to allow the same rfq creation using different recent timestamps
whitelist: Option<Pubkey>,
) -> Result<()> {
create_rfq_instruction(
ctx,
Expand All @@ -201,7 +198,6 @@ pub mod rfq {
active_window,
settling_window,
recent_timestamp,
whitelist,
)
}

Expand Down Expand Up @@ -329,27 +325,12 @@ pub mod rfq {

pub fn create_whitelist<'info>(
ctx: Context<'_, '_, '_, 'info, CreateWhitelistAccounts<'info>>,
expected_whitelist_size: u16,
whitelist: Vec<Pubkey>,
) -> Result<()> {
create_whitelist_instruction(ctx, expected_whitelist_size, whitelist)
create_whitelist_instruction(ctx, whitelist)
}

pub fn clean_up_whitelist(ctx: Context<CleanUpWhitelistAccounts>) -> Result<()> {
clean_up_whitelist_instruction(ctx)
}

pub fn add_address_to_whitelist(
ctx: Context<AddAddressToWhitelistAccounts>,
address: Pubkey,
) -> Result<()> {
add_address_to_whitelist_instruction(ctx, address)
}

pub fn remove_address_from_whitelist(
ctx: Context<RemoveAddressToWhitelistAccounts>,
address: Pubkey,
) -> Result<()> {
remove_address_from_whitelist_instruction(ctx, address)
}
}
Loading
Loading