diff --git a/programs/mango-v4/src/instructions/group_create.rs b/programs/mango-v4/src/instructions/group_create.rs index 7ba4204a4..b25544f13 100644 --- a/programs/mango-v4/src/instructions/group_create.rs +++ b/programs/mango-v4/src/instructions/group_create.rs @@ -9,14 +9,14 @@ use crate::state::*; pub struct GroupCreate<'info> { #[account( init, - seeds = [b"Group".as_ref(), admin.key().as_ref(), &group_num.to_le_bytes()], + seeds = [b"Group".as_ref(), creator.key().as_ref(), &group_num.to_le_bytes()], bump, payer = payer, space = 8 + std::mem::size_of::(), )] pub group: AccountLoader<'info, Group>, - pub admin: Signer<'info>, + pub creator: Signer<'info>, pub insurance_mint: Account<'info, Mint>, @@ -40,7 +40,9 @@ pub struct GroupCreate<'info> { pub fn group_create(ctx: Context, group_num: u32, testing: u8) -> Result<()> { let mut group = ctx.accounts.group.load_init()?; - group.admin = ctx.accounts.admin.key(); + group.creator = ctx.accounts.creator.key(); + group.admin = ctx.accounts.creator.key(); + group.fast_listing_admin = Pubkey::default(); group.insurance_vault = ctx.accounts.insurance_vault.key(); group.insurance_mint = ctx.accounts.insurance_mint.key(); group.bump = *ctx.bumps.get("group").ok_or(MangoError::SomeError)?; diff --git a/programs/mango-v4/src/instructions/group_edit.rs b/programs/mango-v4/src/instructions/group_edit.rs new file mode 100644 index 000000000..8d8b9822d --- /dev/null +++ b/programs/mango-v4/src/instructions/group_edit.rs @@ -0,0 +1,26 @@ +use anchor_lang::prelude::*; + +use crate::state::*; + +#[derive(Accounts)] +pub struct GroupEdit<'info> { + #[account( + mut, + has_one = admin, + )] + pub group: AccountLoader<'info, Group>, + pub admin: Signer<'info>, +} + +// use case - transfer group ownership to governance, where +// new_admin and new_fast_listing_admin are PDAs +pub fn group_edit( + ctx: Context, + new_admin: Pubkey, + new_fast_listing_admin: Pubkey, +) -> Result<()> { + let mut group = ctx.accounts.group.load_mut()?; + group.admin = new_admin; + group.fast_listing_admin = new_fast_listing_admin; + Ok(()) +} diff --git a/programs/mango-v4/src/instructions/mod.rs b/programs/mango-v4/src/instructions/mod.rs index b9ac42769..9a8445afa 100644 --- a/programs/mango-v4/src/instructions/mod.rs +++ b/programs/mango-v4/src/instructions/mod.rs @@ -9,6 +9,7 @@ pub use flash_loan2::*; pub use flash_loan3::*; pub use group_close::*; pub use group_create::*; +pub use group_edit::*; pub use liq_token_bankruptcy::*; pub use liq_token_with_token::*; pub use perp_cancel_all_orders::*; @@ -52,6 +53,7 @@ mod flash_loan2; mod flash_loan3; mod group_close; mod group_create; +mod group_edit; mod liq_token_bankruptcy; mod liq_token_with_token; mod perp_cancel_all_orders; diff --git a/programs/mango-v4/src/lib.rs b/programs/mango-v4/src/lib.rs index 6a1f8ae86..8b739b360 100644 --- a/programs/mango-v4/src/lib.rs +++ b/programs/mango-v4/src/lib.rs @@ -36,6 +36,14 @@ pub mod mango_v4 { instructions::group_create(ctx, group_num, testing) } + pub fn group_edit( + ctx: Context, + new_admin: Pubkey, + new_fast_listing_admin: Pubkey, + ) -> Result<()> { + instructions::group_edit(ctx, new_admin, new_fast_listing_admin) + } + pub fn group_close(ctx: Context) -> Result<()> { instructions::group_close(ctx) } diff --git a/programs/mango-v4/src/state/group.rs b/programs/mango-v4/src/state/group.rs index bff800706..971b988b1 100644 --- a/programs/mango-v4/src/state/group.rs +++ b/programs/mango-v4/src/state/group.rs @@ -10,11 +10,16 @@ pub const QUOTE_TOKEN_INDEX: TokenIndex = 0; #[derive(Debug)] pub struct Group { // ABI: Clients rely on this being at offset 8 - pub admin: Pubkey, + pub creator: Pubkey, // ABI: Clients rely on this being at offset 40 pub group_num: u32, + pub admin: Pubkey, + + // TODO: unused, use case - listing shit tokens with conservative parameters (mostly defaults) + pub fast_listing_admin: Pubkey, + pub padding: [u8; 4], pub insurance_vault: Pubkey, @@ -27,15 +32,16 @@ pub struct Group { pub padding2: [u8; 6], pub reserved: [u8; 8], } -const_assert_eq!(size_of::(), 32 * 3 + 4 + 4 + 1 * 2 + 6 + 8); +const_assert_eq!(size_of::(), 32 * 5 + 4 + 4 + 1 * 2 + 6 + 8); const_assert_eq!(size_of::() % 8, 0); +// note: using creator instead of admin, since admin can be changed #[macro_export] macro_rules! group_seeds { ( $group:expr ) => { &[ b"Group".as_ref(), - $group.admin.as_ref(), + $group.creator.as_ref(), &$group.group_num.to_le_bytes(), &[$group.bump], ] diff --git a/programs/mango-v4/tests/program_test/mango_client.rs b/programs/mango-v4/tests/program_test/mango_client.rs index 2dd9f7455..7372b0413 100644 --- a/programs/mango-v4/tests/program_test/mango_client.rs +++ b/programs/mango-v4/tests/program_test/mango_client.rs @@ -1214,7 +1214,7 @@ impl<'keypair> ClientInstruction for StubOracleCloseInstruction<'keypair> { } pub struct GroupCreateInstruction<'keypair> { - pub admin: &'keypair Keypair, + pub creator: &'keypair Keypair, pub payer: &'keypair Keypair, pub insurance_mint: Pubkey, } @@ -1235,7 +1235,7 @@ impl<'keypair> ClientInstruction for GroupCreateInstruction<'keypair> { let group = Pubkey::find_program_address( &[ b"Group".as_ref(), - self.admin.pubkey().as_ref(), + self.creator.pubkey().as_ref(), &instruction.group_num.to_le_bytes(), ], &program_id, @@ -1250,7 +1250,8 @@ impl<'keypair> ClientInstruction for GroupCreateInstruction<'keypair> { let accounts = Self::Accounts { group, - admin: self.admin.pubkey(), + creator: self.creator.pubkey(), + admin: self.creator.pubkey(), insurance_mint: self.insurance_mint, insurance_vault, payer: self.payer.pubkey(), @@ -1264,7 +1265,7 @@ impl<'keypair> ClientInstruction for GroupCreateInstruction<'keypair> { } fn signers(&self) -> Vec<&Keypair> { - vec![self.admin, self.payer] + vec![self.creator, self.payer] } } diff --git a/programs/mango-v4/tests/program_test/mango_setup.rs b/programs/mango-v4/tests/program_test/mango_setup.rs index e0a5b066b..20809b46d 100644 --- a/programs/mango-v4/tests/program_test/mango_setup.rs +++ b/programs/mango-v4/tests/program_test/mango_setup.rs @@ -39,7 +39,7 @@ impl<'a> GroupWithTokensConfig<'a> { let create_group_accounts = send_tx( solana, GroupCreateInstruction { - admin, + creator: admin, payer, insurance_mint: mints[0].pubkey, },