-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/update share, add user, remove user #16
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
base: release_0.1.2
Are you sure you want to change the base?
Changes from all commits
b84bbbb
a8a46db
3ef93aa
3be39f2
2561964
3cf2cd7
e63211b
e9fffc7
bf5760a
0f963eb
ab2aeb9
1a05433
92ee278
1f70893
a3cc414
9b24620
681d89c
c8dabc7
5861fb5
f526a47
7b8a733
f1483ef
ca85f20
a93020a
8033c8d
7ef755e
c399252
2cd65fe
4e40252
23ce64e
b73dc9e
e7b4498
365449a
87bed87
30c0fa6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| [toolchain] | ||
| anchor_version = "0.31.1" | ||
| solana_version = "2.3.13" | ||
| package_manager = "yarn" | ||
|
|
||
| [features] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,16 @@ | ||
| use anchor_lang::prelude::Pubkey; | ||
| use anchor_lang::Discriminator; | ||
|
|
||
| pub const MAX_USER: usize = 5; | ||
| pub const MIN_USER: usize = 2; | ||
| pub const MAX_STATIC_USER: usize = 5; | ||
| pub const MAX_USER: usize = 100; // 5 static users + 95 dynamic users; this is an arbitrary limit | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. leaving it at 100 for now. Since I don't know if there is a demand for more. We can increase the limit. |
||
| pub const PRECISION_SCALE: u8 = 64; | ||
|
|
||
| pub mod seeds { | ||
| pub const FEE_VAULT_PREFIX: &[u8] = b"fee_vault"; | ||
| pub const FEE_VAULT_AUTHORITY_PREFIX: &[u8] = b"fee_vault_authority"; | ||
| pub const TOKEN_VAULT_PREFIX: &[u8] = b"token_vault"; | ||
| pub const USER_UNCLAIMED_FEE_PREFIX: &[u8] = b"user_unclaimed_fee"; | ||
| } | ||
|
|
||
| // (program_id, instruction, index_of_token_vault_account) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,8 +23,8 @@ pub enum FeeVaultError { | |
| #[msg("Invalid user address")] | ||
| InvalidUserAddress, | ||
|
|
||
| #[msg("Exceeded number of users allowed")] | ||
| ExceededUser, | ||
| #[msg("Invalid number of users")] | ||
| InvalidNumberOfUsers, | ||
|
Comment on lines
+26
to
+27
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing the error name here since. This error is also used when the number of user is less than the minimum amount (2) |
||
|
|
||
| #[msg("Invalid fee vault")] | ||
| InvalidFeeVault, | ||
|
|
@@ -34,4 +34,16 @@ pub enum FeeVaultError { | |
|
|
||
| #[msg("Invalid action")] | ||
| InvalidAction, | ||
|
|
||
| #[msg("Invalid permission")] | ||
| InvalidPermission, | ||
|
|
||
| #[msg("Invalid operator address")] | ||
| InvalidOperatorAddress, | ||
|
|
||
| #[msg("Type cast error")] | ||
| TypeCastFailed, | ||
|
|
||
| #[msg("Fee vault is not mutable")] | ||
| FeeVaultNotMutable, | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| use crate::const_pda; | ||
| use crate::constants::seeds::USER_UNCLAIMED_FEE_PREFIX; | ||
| use crate::event::EvtClaimUnclaimedFee; | ||
| use crate::state::{FeeVault, UserUnclaimedFee}; | ||
| use crate::utils::token::transfer_from_fee_vault; | ||
| use anchor_lang::prelude::*; | ||
| use anchor_spl::token_interface::{Mint, TokenAccount, TokenInterface}; | ||
|
|
||
| #[event_cpi] | ||
| #[derive(Accounts)] | ||
| pub struct ClaimUnclaimedFeeCtx<'info> { | ||
| #[account(has_one = token_mint, has_one = operator, has_one = token_vault)] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. user should pass the current operator
bangyro marked this conversation as resolved.
|
||
| pub fee_vault: AccountLoader<'info, FeeVault>, | ||
|
|
||
| /// CHECK: fee vault authority | ||
| #[account(address = const_pda::fee_vault_authority::ID)] | ||
| pub fee_vault_authority: UncheckedAccount<'info>, | ||
|
|
||
| pub token_mint: Box<InterfaceAccount<'info, Mint>>, | ||
|
|
||
| #[account(mut)] | ||
| pub token_vault: Box<InterfaceAccount<'info, TokenAccount>>, | ||
|
|
||
| #[account( | ||
| mut, | ||
| close = operator, | ||
| seeds = [ | ||
|
bangyro marked this conversation as resolved.
|
||
| USER_UNCLAIMED_FEE_PREFIX, | ||
| fee_vault.key().as_ref(), | ||
| user.key().as_ref(), | ||
| ], | ||
| bump, | ||
| )] | ||
| pub user_unclaimed_fee: AccountLoader<'info, UserUnclaimedFee>, | ||
|
|
||
| // token account does not need to be owned by user | ||
| #[account(mut)] | ||
| pub user_token_vault: Box<InterfaceAccount<'info, TokenAccount>>, | ||
|
|
||
| /// CHECK: fee vault operator, receives rent from closed account | ||
| #[account(mut)] | ||
| pub operator: UncheckedAccount<'info>, | ||
|
|
||
| pub user: Signer<'info>, | ||
|
|
||
| pub token_program: Interface<'info, TokenInterface>, | ||
| } | ||
|
|
||
| // when a user is removed from a fee vault, they may claim any unclaimed fee that they have earned before the removal | ||
| pub fn handle_claim_unclaimed_fee(ctx: Context<ClaimUnclaimedFeeCtx>) -> Result<()> { | ||
| let user_unclaimed_fee = ctx.accounts.user_unclaimed_fee.load()?; | ||
| let fee_being_claimed = user_unclaimed_fee.unclaimed_fee; | ||
|
|
||
| if fee_being_claimed > 0 { | ||
| transfer_from_fee_vault( | ||
| ctx.accounts.fee_vault_authority.to_account_info(), | ||
| &ctx.accounts.token_mint, | ||
| ctx.accounts.token_vault.to_account_info(), | ||
| ctx.accounts.user_token_vault.to_account_info(), | ||
| &ctx.accounts.token_program, | ||
| fee_being_claimed, | ||
| )?; | ||
|
|
||
| emit_cpi!(EvtClaimUnclaimedFee { | ||
| fee_vault: ctx.accounts.fee_vault.key(), | ||
| user: ctx.accounts.user.key(), | ||
| claimed_fee: fee_being_claimed, | ||
| }); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| use crate::constants::WHITELISTED_ACTIONS; | ||
| use crate::event::EvtFundFee; | ||
| use crate::state::FeeVault; | ||
| use crate::math::SafeCast; | ||
| use crate::state::{DynamicFeeVaultLoader, FeeVault, FeeVaultType}; | ||
| use crate::{error::FeeVaultError, math::SafeMath}; | ||
| use anchor_lang::prelude::*; | ||
| use anchor_lang::solana_program::{instruction::Instruction, program::invoke_signed}; | ||
|
|
@@ -22,11 +23,11 @@ pub struct FundByClaimingFeeCtx<'info> { | |
| pub source_program: UncheckedAccount<'info>, | ||
| } | ||
|
|
||
| pub fn is_support_action<'info>( | ||
| pub fn is_support_action( | ||
| source_program: &Pubkey, | ||
| discriminator: &[u8], | ||
| token_vault: Pubkey, | ||
| remaining_accounts: &[AccountInfo<'info>], | ||
| remaining_accounts: &[AccountInfo], | ||
| ) -> bool { | ||
| for &(program, disc, token_vault_index) in WHITELISTED_ACTIONS.iter() { | ||
| if program.eq(source_program) && disc.eq(discriminator) { | ||
|
|
@@ -53,29 +54,34 @@ pub fn handle_fund_by_claiming_fee( | |
| FeeVaultError::InvalidAction | ||
| ); | ||
|
|
||
| let fee_vault = ctx.accounts.fee_vault.load()?; | ||
| let vault = ctx.accounts.fee_vault.load_content_mut()?; | ||
|
|
||
| require!( | ||
| fee_vault.is_share_holder(ctx.accounts.signer.key), | ||
| vault.is_share_holder(ctx.accounts.signer.key), | ||
| FeeVaultError::InvalidSigner | ||
| ); | ||
|
|
||
| // support fee vault type is pda account | ||
| require!( | ||
| fee_vault.fee_vault_type == 1, | ||
| vault.fee_vault.fee_vault_type.safe_cast()? == FeeVaultType::PdaAccount, | ||
| FeeVaultError::InvalidFeeVault | ||
| ); | ||
|
|
||
| let base = vault.fee_vault.base; | ||
| let token_mint = vault.fee_vault.token_mint; | ||
| let fee_vault_bump = vault.fee_vault.fee_vault_bump; | ||
| drop(vault); | ||
|
Comment on lines
+70
to
+73
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved up since we have to drop the |
||
|
|
||
| let before_token_vault_balance = ctx.accounts.token_vault.amount; | ||
|
|
||
| let accounts: Vec<AccountMeta> = ctx | ||
| .remaining_accounts | ||
| .iter() | ||
| .map(|acc| { | ||
| let is_signer = acc.key == &ctx.accounts.fee_vault.key(); | ||
| let is_signer = acc.key.eq(&ctx.accounts.fee_vault.key()); | ||
| AccountMeta { | ||
| pubkey: *acc.key, | ||
| is_signer: is_signer, | ||
| is_signer, | ||
| is_writable: acc.is_writable, | ||
| } | ||
| }) | ||
|
|
@@ -87,11 +93,7 @@ pub fn handle_fund_by_claiming_fee( | |
| .map(|acc| AccountInfo { ..acc.clone() }) | ||
| .collect(); | ||
| // invoke instruction to amm | ||
| let base = fee_vault.base; | ||
| let token_mint = fee_vault.token_mint; | ||
| let fee_vault_bump = fee_vault.fee_vault_bump; | ||
| let signer_seeds = fee_vault_seeds!(base, token_mint, fee_vault_bump); | ||
| drop(fee_vault); | ||
|
|
||
| invoke_signed( | ||
| &Instruction { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.