Fees to dao (#644)

* withdraw fees to dao

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* rename

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

* Fixes from review

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>

---------

Signed-off-by: microwavedcola1 <microwavedcola@gmail.com>
This commit is contained in:
microwavedcola1 2023-07-13 18:22:35 +02:00 committed by GitHub
parent db8f5ae30d
commit 40a011a48e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 236 additions and 7 deletions

View File

@ -0,0 +1,52 @@
use anchor_lang::prelude::*;
use anchor_spl::token;
use anchor_spl::token::Token;
use anchor_spl::token::TokenAccount;
use crate::error::*;
use crate::state::*;
#[derive(Accounts)]
pub struct AdminPerpWithdrawFees<'info> {
#[account(
constraint = group.load()?.is_ix_enabled(IxGate::AdminPerpWithdrawFees) @ MangoError::IxIsDisabled,
has_one = admin,
)]
pub group: AccountLoader<'info, Group>,
#[account(
mut,
has_one = group,
)]
pub perp_market: AccountLoader<'info, PerpMarket>,
#[account(
mut,
has_one = group,
has_one = vault,
constraint = bank.load()?.token_index == perp_market.load()?.settle_token_index
)]
pub bank: AccountLoader<'info, Bank>,
#[account(mut)]
pub vault: Account<'info, TokenAccount>,
#[account(mut)]
pub token_account: Box<Account<'info, TokenAccount>>,
pub token_program: Program<'info, Token>,
pub admin: Signer<'info>,
}
impl<'info> AdminPerpWithdrawFees<'info> {
pub fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
let program = self.token_program.to_account_info();
let accounts = token::Transfer {
from: self.vault.to_account_info(),
to: self.token_account.to_account_info(),
authority: self.group.to_account_info(),
};
CpiContext::new(program, accounts)
}
}

View File

@ -0,0 +1,45 @@
use anchor_lang::prelude::*;
use anchor_spl::token;
use anchor_spl::token::Token;
use anchor_spl::token::TokenAccount;
use crate::error::*;
use crate::state::*;
#[derive(Accounts)]
pub struct AdminTokenWithdrawFees<'info> {
#[account(
constraint = group.load()?.is_ix_enabled(IxGate::AdminTokenWithdrawFees) @ MangoError::IxIsDisabled,
has_one = admin,
)]
pub group: AccountLoader<'info, Group>,
#[account(
mut,
has_one = group,
has_one = vault,
)]
pub bank: AccountLoader<'info, Bank>,
#[account(mut)]
pub vault: Account<'info, TokenAccount>,
#[account(mut)]
pub token_account: Box<Account<'info, TokenAccount>>,
pub token_program: Program<'info, Token>,
pub admin: Signer<'info>,
}
impl<'info> AdminTokenWithdrawFees<'info> {
pub fn transfer_ctx(&self) -> CpiContext<'_, '_, '_, 'info, token::Transfer<'info>> {
let program = self.token_program.to_account_info();
let accounts = token::Transfer {
from: self.vault.to_account_info(),
to: self.token_account.to_account_info(),
authority: self.group.to_account_info(),
};
CpiContext::new(program, accounts)
}
}

View File

@ -5,6 +5,8 @@ pub use account_create::*;
pub use account_edit::*;
pub use account_expand::*;
pub use account_toggle_freeze::*;
pub use admin_perp_withdraw_fees::*;
pub use admin_token_withdraw_fees::*;
pub use alt_extend::*;
pub use alt_set::*;
pub use benchmark::*;
@ -77,6 +79,8 @@ mod account_create;
mod account_edit;
mod account_expand;
mod account_toggle_freeze;
mod admin_perp_withdraw_fees;
mod admin_token_withdraw_fees;
mod alt_extend;
mod alt_set;
mod benchmark;

View File

@ -0,0 +1,21 @@
use anchor_lang::prelude::*;
use anchor_spl::token;
use crate::{accounts_ix::*, group_seeds};
pub fn admin_perp_withdraw_fees(ctx: Context<AdminPerpWithdrawFees>) -> Result<()> {
let group = ctx.accounts.group.load()?;
let mut perp_market = ctx.accounts.perp_market.load_mut()?;
let group_seeds = group_seeds!(group);
let fees = perp_market.fees_settled.floor().to_num::<u64>() - perp_market.fees_withdrawn;
let amount = fees.min(ctx.accounts.vault.amount);
token::transfer(
ctx.accounts.transfer_ctx().with_signer(&[group_seeds]),
amount,
)?;
perp_market.fees_withdrawn += amount;
Ok(())
}

View File

@ -0,0 +1,21 @@
use anchor_lang::prelude::*;
use anchor_spl::token;
use crate::{accounts_ix::*, group_seeds};
pub fn admin_withdraw_token_fees(ctx: Context<AdminTokenWithdrawFees>) -> Result<()> {
let group = ctx.accounts.group.load()?;
let mut bank = ctx.accounts.bank.load_mut()?;
let group_seeds = group_seeds!(group);
let fees = bank.collected_fees_native.floor().to_num::<u64>() - bank.fees_withdrawn;
let amount = fees.min(ctx.accounts.vault.amount);
token::transfer(
ctx.accounts.transfer_ctx().with_signer(&[group_seeds]),
amount,
)?;
bank.fees_withdrawn += amount;
Ok(())
}

View File

@ -70,6 +70,18 @@ pub fn ix_gate_set(ctx: Context<IxGateSet>, ix_gate: u128) -> Result<()> {
log_if_changed(&group, ix_gate, IxGate::TokenConditionalSwapCreate);
log_if_changed(&group, ix_gate, IxGate::TokenConditionalSwapTrigger);
log_if_changed(&group, ix_gate, IxGate::TokenConditionalSwapCancel);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2CancelOrder);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2CloseOpenOrders);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2CreateOpenOrders);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2DeregisterMarket);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2EditMarket);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2LiqForceCancelOrders);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2PlaceOrder);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2PlaceTakeOrder);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2RegisterMarket);
log_if_changed(&group, ix_gate, IxGate::OpenbookV2SettleFunds);
log_if_changed(&group, ix_gate, IxGate::AdminTokenWithdrawFees);
log_if_changed(&group, ix_gate, IxGate::AdminPerpWithdrawFees);
group.ix_gate = ix_gate;

View File

@ -4,6 +4,8 @@ pub use account_create::*;
pub use account_edit::*;
pub use account_expand::*;
pub use account_toggle_freeze::*;
pub use admin_perp_withdraw_fees::*;
pub use admin_withdraw_token_fees::*;
pub use alt_extend::*;
pub use alt_set::*;
pub use benchmark::*;
@ -66,6 +68,8 @@ mod account_create;
mod account_edit;
mod account_expand;
mod account_toggle_freeze;
mod admin_perp_withdraw_fees;
mod admin_withdraw_token_fees;
mod alt_extend;
mod alt_set;
mod benchmark;

View File

@ -75,7 +75,9 @@ pub fn token_register_trustless(
deposit_weight_scale_start_quote: 5_000_000_000.0, // $5k
reduce_only: 2, // deposit-only
force_close: 0,
reserved: [0; 2118],
padding: [0; 6],
fees_withdrawn: 0,
reserved: [0; 2104],
};
require_gt!(bank.max_rate, MINIMUM_MAX_RATE);

View File

@ -43,6 +43,18 @@ pub mod mango_v4 {
use super::*;
use error::*;
pub fn admin_withdraw_token_fees(ctx: Context<AdminTokenWithdrawFees>) -> Result<()> {
#[cfg(feature = "enable-gpl")]
instructions::admin_withdraw_token_fees(ctx)?;
Ok(())
}
pub fn admin_perp_withdraw_fees(ctx: Context<AdminPerpWithdrawFees>) -> Result<()> {
#[cfg(feature = "enable-gpl")]
instructions::admin_perp_withdraw_fees(ctx)?;
Ok(())
}
pub fn group_create(
ctx: Context<GroupCreate>,
group_num: u32,

View File

@ -136,8 +136,14 @@ pub struct Bank {
pub reduce_only: u8,
pub force_close: u8,
pub padding: [u8; 6],
// Do separate bookkeping for how many tokens were withdrawn
// This ensures that collected_fees_native is strictly increasing for stats gathering purposes
pub fees_withdrawn: u64,
#[derivative(Debug = "ignore")]
pub reserved: [u8; 2118],
pub reserved: [u8; 2104],
}
const_assert_eq!(
size_of::<Bank>(),
@ -166,7 +172,9 @@ const_assert_eq!(
+ 8
+ 1
+ 1
+ 2118
+ 6
+ 8
+ 2104
);
const_assert_eq!(size_of::<Bank>(), 3064);
const_assert_eq!(size_of::<Bank>() % 8, 0);
@ -240,7 +248,9 @@ impl Bank {
deposit_weight_scale_start_quote: f64::MAX,
reduce_only: 0,
force_close: 0,
reserved: [0; 2118],
padding: [0; 6],
fees_withdrawn: 0,
reserved: [0; 2104],
}
}

View File

@ -211,6 +211,8 @@ pub enum IxGate {
OpenbookV2PlaceTakeOrder = 62,
OpenbookV2RegisterMarket = 63,
OpenbookV2SettleFunds = 64,
AdminTokenWithdrawFees = 65,
AdminPerpWithdrawFees = 66,
// NOTE: Adding new variants requires matching changes in ts and the ix_gate_set instruction.
}

View File

@ -124,8 +124,10 @@ pub struct PerpMarket {
pub taker_fee: I80F48,
/// Fees accrued in native quote currency
/// these are increased when new fees are paid and decreased when perp_settle_fees is called
pub fees_accrued: I80F48,
/// Fees settled in native quote currency
/// these are increased when perp_settle_fees is called, and never decreased
pub fees_settled: I80F48,
/// Fee (in quote native) to charge for ioc orders
@ -170,7 +172,11 @@ pub struct PerpMarket {
pub positive_pnl_liquidation_fee: I80F48,
pub reserved: [u8; 1888],
// Do separate bookkeping for how many tokens were withdrawn
// This ensures that fees_settled is strictly increasing for stats gathering purposes
pub fees_withdrawn: u64,
pub reserved: [u8; 1880],
}
const_assert_eq!(
@ -206,7 +212,8 @@ const_assert_eq!(
+ 1
+ 7
+ 3 * 16
+ 1888
+ 8
+ 1880
);
const_assert_eq!(size_of::<PerpMarket>(), 2808);
const_assert_eq!(size_of::<PerpMarket>() % 8, 0);
@ -495,7 +502,8 @@ impl PerpMarket {
maint_overall_asset_weight: I80F48::ONE,
init_overall_asset_weight: I80F48::ONE,
positive_pnl_liquidation_fee: I80F48::ZERO,
reserved: [0; 1888],
fees_withdrawn: 0,
reserved: [0; 1880],
}
}
}

View File

@ -182,6 +182,18 @@ export interface IxGateParams {
TokenConditionalSwapCreate: boolean;
TokenConditionalSwapTrigger: boolean;
TokenConditionalSwapCancel: boolean;
OpenbookV2CancelOrder: boolean;
OpenbookV2CloseOpenOrders: boolean;
OpenbookV2CreateOpenOrders: boolean;
OpenbookV2DeregisterMarket: boolean;
OpenbookV2EditMarket: boolean;
OpenbookV2LiqForceCancelOrders: boolean;
OpenbookV2PlaceOrder: boolean;
OpenbookV2PlaceTakeOrder: boolean;
OpenbookV2RegisterMarket: boolean;
OpenbookV2SettleFunds: boolean;
AdminTokenWithdrawFees: boolean;
AdminPerpWithdrawFees: boolean;
}
// Default with all ixs enabled, use with buildIxGate
@ -244,6 +256,18 @@ export const TrueIxGateParams: IxGateParams = {
TokenConditionalSwapCreate: true,
TokenConditionalSwapTrigger: true,
TokenConditionalSwapCancel: true,
OpenbookV2CancelOrder: true,
OpenbookV2CloseOpenOrders: true,
OpenbookV2CreateOpenOrders: true,
OpenbookV2DeregisterMarket: true,
OpenbookV2EditMarket: true,
OpenbookV2LiqForceCancelOrders: true,
OpenbookV2PlaceOrder: true,
OpenbookV2PlaceTakeOrder: true,
OpenbookV2RegisterMarket: true,
OpenbookV2SettleFunds: true,
AdminTokenWithdrawFees: true,
AdminPerpWithdrawFees: true,
};
// build ix gate e.g. buildIxGate(Builder(TrueIxGateParams).TokenDeposit(false).build()).toNumber(),
@ -316,6 +340,18 @@ export function buildIxGate(p: IxGateParams): BN {
toggleIx(ixGate, p, 'TokenConditionalSwapCreate', 52);
toggleIx(ixGate, p, 'TokenConditionalSwapTrigger', 53);
toggleIx(ixGate, p, 'TokenConditionalSwapCancel', 54);
toggleIx(ixGate, p, 'OpenbookV2CancelOrder', 55);
toggleIx(ixGate, p, 'OpenbookV2CloseOpenOrders', 56);
toggleIx(ixGate, p, 'OpenbookV2CreateOpenOrders', 57);
toggleIx(ixGate, p, 'OpenbookV2DeregisterMarket', 58);
toggleIx(ixGate, p, 'OpenbookV2EditMarket', 59);
toggleIx(ixGate, p, 'OpenbookV2LiqForceCancelOrders', 60);
toggleIx(ixGate, p, 'OpenbookV2PlaceOrder', 61);
toggleIx(ixGate, p, 'OpenbookV2PlaceTakeOrder', 62);
toggleIx(ixGate, p, 'OpenbookV2RegisterMarket', 63);
toggleIx(ixGate, p, 'OpenbookV2SettleFunds', 63);
toggleIx(ixGate, p, 'AdminTokenWithdrawFees', 65);
toggleIx(ixGate, p, 'AdminPerpWithdrawFees', 66);
return ixGate;
}