mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-07-25 23:23:11 +00:00
feat: protect from public pda griefing attacks
This commit is contained in:
@@ -2,11 +2,11 @@ use std::num::NonZeroU128;
|
||||
|
||||
use amm_core::{
|
||||
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
|
||||
compute_pool_pda, compute_vault_pda,
|
||||
compute_pool_pda, compute_pool_pda_seed, compute_vault_pda, compute_vault_pda_seed,
|
||||
};
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::{AccountPostState, ChainedCall, ProgramId},
|
||||
program::{AccountPostState, ChainedCall, Claim, ProgramId},
|
||||
};
|
||||
|
||||
#[expect(clippy::too_many_arguments, reason = "TODO: Fix later")]
|
||||
@@ -108,36 +108,52 @@ pub fn new_definition(
|
||||
};
|
||||
|
||||
pool_post.data = Data::from(&pool_post_definition);
|
||||
let pool_post = AccountPostState::new_claimed_if_default(pool_post);
|
||||
let pool_pda_seed = compute_pool_pda_seed(definition_token_a_id, definition_token_b_id);
|
||||
let pool_post = AccountPostState::new_claimed_if_default(pool_post, Claim::Pda(pool_pda_seed));
|
||||
|
||||
let token_program_id = user_holding_a.account.program_owner;
|
||||
|
||||
// Chain call for Token A (user_holding_a -> Vault_A)
|
||||
let vault_a_seed = compute_vault_pda_seed(pool.account_id, definition_token_a_id);
|
||||
let vault_a_authorized = AccountWithMetadata {
|
||||
is_authorized: true,
|
||||
..vault_a.clone()
|
||||
};
|
||||
let call_token_a = ChainedCall::new(
|
||||
token_program_id,
|
||||
vec![user_holding_a.clone(), vault_a.clone()],
|
||||
vec![user_holding_a.clone(), vault_a_authorized],
|
||||
&token_core::Instruction::Transfer {
|
||||
amount_to_transfer: token_a_amount.into(),
|
||||
},
|
||||
);
|
||||
)
|
||||
.with_pda_seeds(vec![vault_a_seed]);
|
||||
|
||||
// Chain call for Token B (user_holding_b -> Vault_B)
|
||||
let vault_b_seed = compute_vault_pda_seed(pool.account_id, definition_token_b_id);
|
||||
let vault_b_authorized = AccountWithMetadata {
|
||||
is_authorized: true,
|
||||
..vault_b.clone()
|
||||
};
|
||||
let call_token_b = ChainedCall::new(
|
||||
token_program_id,
|
||||
vec![user_holding_b.clone(), vault_b.clone()],
|
||||
vec![user_holding_b.clone(), vault_b_authorized],
|
||||
&token_core::Instruction::Transfer {
|
||||
amount_to_transfer: token_b_amount.into(),
|
||||
},
|
||||
);
|
||||
|
||||
let mut pool_lp_auth = pool_definition_lp.clone();
|
||||
pool_lp_auth.is_authorized = true;
|
||||
)
|
||||
.with_pda_seeds(vec![vault_b_seed]);
|
||||
|
||||
let pool_lp_pda_seed = compute_liquidity_token_pda_seed(pool.account_id);
|
||||
let pool_lp_authorized = AccountWithMetadata {
|
||||
is_authorized: true,
|
||||
..pool_definition_lp.clone()
|
||||
};
|
||||
let call_token_lp = ChainedCall::new(
|
||||
token_program_id,
|
||||
vec![pool_lp_auth, user_holding_lp.clone()],
|
||||
vec![pool_lp_authorized, user_holding_lp.clone()],
|
||||
&instruction,
|
||||
)
|
||||
.with_pda_seeds(vec![compute_liquidity_token_pda_seed(pool.account_id)]);
|
||||
.with_pda_seeds(vec![pool_lp_pda_seed]);
|
||||
|
||||
let chained_calls = vec![call_token_lp, call_token_b, call_token_a];
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::num::NonZero;
|
||||
use std::{num::NonZero, vec};
|
||||
|
||||
use amm_core::{
|
||||
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
|
||||
@@ -1756,7 +1756,7 @@ impl AccountsForExeTests {
|
||||
definition_id: IdForExeTests::token_lp_definition_id(),
|
||||
balance: BalanceForExeTests::lp_supply_init(),
|
||||
}),
|
||||
nonce: 0_u128.into(),
|
||||
nonce: 1_u128.into(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1801,7 +1801,7 @@ impl AccountsForExeTests {
|
||||
definition_id: IdForExeTests::token_lp_definition_id(),
|
||||
balance: 0,
|
||||
}),
|
||||
nonce: 0_u128.into(),
|
||||
nonce: 1.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2799,7 +2799,7 @@ fn simple_amm_new_definition_inactive_initialized_pool_and_uninit_user_lp() {
|
||||
IdForExeTests::user_token_b_id(),
|
||||
IdForExeTests::user_token_lp_id(),
|
||||
],
|
||||
vec![0_u128.into(), 0_u128.into()],
|
||||
vec![0_u128.into(), 0_u128.into(), 0_u128.into()],
|
||||
instruction,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -2809,6 +2809,7 @@ fn simple_amm_new_definition_inactive_initialized_pool_and_uninit_user_lp() {
|
||||
&[
|
||||
&PrivateKeysForTests::user_token_a_key(),
|
||||
&PrivateKeysForTests::user_token_b_key(),
|
||||
&PrivateKeysForTests::user_token_lp_key(),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -2955,7 +2956,7 @@ fn simple_amm_new_definition_uninitialized_pool() {
|
||||
IdForExeTests::user_token_b_id(),
|
||||
IdForExeTests::user_token_lp_id(),
|
||||
],
|
||||
vec![0_u128.into(), 0_u128.into()],
|
||||
vec![0_u128.into(), 0_u128.into(), 0_u128.into()],
|
||||
instruction,
|
||||
)
|
||||
.unwrap();
|
||||
@@ -2965,6 +2966,7 @@ fn simple_amm_new_definition_uninitialized_pool() {
|
||||
&[
|
||||
&PrivateKeysForTests::user_token_a_key(),
|
||||
&PrivateKeysForTests::user_token_b_key(),
|
||||
&PrivateKeysForTests::user_token_lp_key(),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata},
|
||||
program::{AccountPostState, ChainedCall, ProgramId},
|
||||
program::{AccountPostState, ChainedCall, Claim, ProgramId},
|
||||
};
|
||||
|
||||
pub fn create_associated_token_account(
|
||||
@@ -11,7 +11,7 @@ pub fn create_associated_token_account(
|
||||
) -> (Vec<AccountPostState>, Vec<ChainedCall>) {
|
||||
// No authorization check needed: create is idempotent, so anyone can call it safely.
|
||||
let token_program_id = token_definition.account.program_owner;
|
||||
ata_core::verify_ata_and_get_seed(
|
||||
let ata_seed = ata_core::verify_ata_and_get_seed(
|
||||
&ata_account,
|
||||
&owner,
|
||||
token_definition.account_id,
|
||||
@@ -22,7 +22,7 @@ pub fn create_associated_token_account(
|
||||
if ata_account.account != Account::default() {
|
||||
return (
|
||||
vec![
|
||||
AccountPostState::new_claimed_if_default(owner.account.clone()),
|
||||
AccountPostState::new_claimed_if_default(owner.account.clone(), Claim::Authorized),
|
||||
AccountPostState::new(token_definition.account.clone()),
|
||||
AccountPostState::new(ata_account.account.clone()),
|
||||
],
|
||||
@@ -31,14 +31,20 @@ pub fn create_associated_token_account(
|
||||
}
|
||||
|
||||
let post_states = vec![
|
||||
AccountPostState::new_claimed_if_default(owner.account.clone()),
|
||||
AccountPostState::new_claimed_if_default(owner.account.clone(), Claim::Authorized),
|
||||
AccountPostState::new(token_definition.account.clone()),
|
||||
AccountPostState::new(ata_account.account.clone()),
|
||||
];
|
||||
let ata_account_auth = AccountWithMetadata {
|
||||
is_authorized: true,
|
||||
..ata_account.clone()
|
||||
};
|
||||
let chained_call = ChainedCall::new(
|
||||
token_program_id,
|
||||
vec![token_definition.clone(), ata_account.clone()],
|
||||
vec![token_definition.clone(), ata_account_auth],
|
||||
&token_core::Instruction::InitializeAccount,
|
||||
);
|
||||
)
|
||||
.with_pda_seeds(vec![ata_seed]);
|
||||
|
||||
(post_states, vec![chained_call])
|
||||
}
|
||||
|
||||
@@ -10,23 +10,23 @@ pub enum Instruction {
|
||||
/// Transfer tokens from sender to recipient.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Sender's Token Holding account (authorized),
|
||||
/// - Recipient's Token Holding account.
|
||||
/// - Sender's Token Holding account (initialized, authorized),
|
||||
/// - Recipient's Token Holding account (initialized or authorized and uninitialized).
|
||||
Transfer { amount_to_transfer: u128 },
|
||||
|
||||
/// Create a new fungible token definition without metadata.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Token Definition account (uninitialized),
|
||||
/// - Token Holding account (uninitialized).
|
||||
/// - Token Definition account (uninitialized, authorized),
|
||||
/// - Token Holding account (uninitialized, authorized).
|
||||
NewFungibleDefinition { name: String, total_supply: u128 },
|
||||
|
||||
/// Create a new fungible or non-fungible token definition with metadata.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Token Definition account (uninitialized),
|
||||
/// - Token Holding account (uninitialized),
|
||||
/// - Token Metadata account (uninitialized).
|
||||
/// - Token Definition account (uninitialized, authorized),
|
||||
/// - Token Holding account (uninitialized, authorized),
|
||||
/// - Token Metadata account (uninitialized, authorized).
|
||||
NewDefinitionWithMetadata {
|
||||
new_definition: NewTokenDefinition,
|
||||
/// Boxed to avoid large enum variant size.
|
||||
@@ -36,29 +36,29 @@ pub enum Instruction {
|
||||
/// Initialize a token holding account for a given token definition.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Token Definition account (initialized),
|
||||
/// - Token Holding account (uninitialized),
|
||||
/// - Token Definition account (initialized, any authorization),
|
||||
/// - Token Holding account (uninitialized, authorized),
|
||||
InitializeAccount,
|
||||
|
||||
/// Burn tokens from the holder's account.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Token Definition account (initialized),
|
||||
/// - Token Holding account (authorized).
|
||||
/// - Token Definition account (initialized, any authorization),
|
||||
/// - Token Holding account (initialized, authorized).
|
||||
Burn { amount_to_burn: u128 },
|
||||
|
||||
/// Mint new tokens to the holder's account.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - Token Definition account (authorized),
|
||||
/// - Token Holding account (uninitialized or initialized).
|
||||
/// - Token Definition account (initialized, authorized),
|
||||
/// - Token Holding account (uninitialized or authorized and initialized).
|
||||
Mint { amount_to_mint: u128 },
|
||||
|
||||
/// Print a new NFT from the master copy.
|
||||
///
|
||||
/// Required accounts:
|
||||
/// - NFT Master Token Holding account (authorized),
|
||||
/// - NFT Printed Copy Token Holding account (uninitialized).
|
||||
/// - NFT Printed Copy Token Holding account (uninitialized, authorized).
|
||||
PrintNft,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::AccountPostState,
|
||||
program::{AccountPostState, Claim},
|
||||
};
|
||||
use token_core::{TokenDefinition, TokenHolding};
|
||||
|
||||
@@ -30,6 +30,6 @@ pub fn initialize_account(
|
||||
|
||||
vec![
|
||||
AccountPostState::new(definition_post),
|
||||
AccountPostState::new_claimed(account_to_initialize),
|
||||
AccountPostState::new_claimed(account_to_initialize, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::AccountPostState,
|
||||
program::{AccountPostState, Claim},
|
||||
};
|
||||
use token_core::{TokenDefinition, TokenHolding};
|
||||
|
||||
@@ -67,6 +67,6 @@ pub fn mint(
|
||||
|
||||
vec![
|
||||
AccountPostState::new(definition_post),
|
||||
AccountPostState::new_claimed_if_default(holding_post),
|
||||
AccountPostState::new_claimed_if_default(holding_post, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::AccountPostState,
|
||||
program::{AccountPostState, Claim},
|
||||
};
|
||||
use token_core::{
|
||||
NewTokenDefinition, NewTokenMetadata, TokenDefinition, TokenHolding, TokenMetadata,
|
||||
@@ -42,8 +42,8 @@ pub fn new_fungible_definition(
|
||||
holding_target_account_post.data = Data::from(&token_holding);
|
||||
|
||||
vec![
|
||||
AccountPostState::new_claimed(definition_target_account_post),
|
||||
AccountPostState::new_claimed(holding_target_account_post),
|
||||
AccountPostState::new_claimed(definition_target_account_post, Claim::Authorized),
|
||||
AccountPostState::new_claimed(holding_target_account_post, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ pub fn new_definition_with_metadata(
|
||||
metadata_target_account_post.data = Data::from(&token_metadata);
|
||||
|
||||
vec![
|
||||
AccountPostState::new_claimed(definition_target_account_post),
|
||||
AccountPostState::new_claimed(holding_target_account_post),
|
||||
AccountPostState::new_claimed(metadata_target_account_post),
|
||||
AccountPostState::new_claimed(definition_target_account_post, Claim::Authorized),
|
||||
AccountPostState::new_claimed(holding_target_account_post, Claim::Authorized),
|
||||
AccountPostState::new_claimed(metadata_target_account_post, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::AccountPostState,
|
||||
program::{AccountPostState, Claim},
|
||||
};
|
||||
use token_core::TokenHolding;
|
||||
|
||||
@@ -50,6 +50,6 @@ pub fn print_nft(
|
||||
|
||||
vec![
|
||||
AccountPostState::new(master_account_post),
|
||||
AccountPostState::new_claimed(printed_account_post),
|
||||
AccountPostState::new_claimed(printed_account_post, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,10 @@
|
||||
reason = "We don't care about it in tests"
|
||||
)]
|
||||
|
||||
use nssa_core::account::{Account, AccountId, AccountWithMetadata, Data};
|
||||
use nssa_core::{
|
||||
account::{Account, AccountId, AccountWithMetadata, Data},
|
||||
program::Claim,
|
||||
};
|
||||
use token_core::{
|
||||
MetadataStandard, NewTokenDefinition, NewTokenMetadata, TokenDefinition, TokenHolding,
|
||||
};
|
||||
@@ -851,7 +854,7 @@ fn mint_uninit_holding_success() {
|
||||
*holding_post.account(),
|
||||
AccountForTests::init_mint().account
|
||||
);
|
||||
assert!(holding_post.requires_claim());
|
||||
assert_eq!(holding_post.required_claim(), Some(Claim::Authorized));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Data},
|
||||
program::AccountPostState,
|
||||
program::{AccountPostState, Claim},
|
||||
};
|
||||
use token_core::TokenHolding;
|
||||
|
||||
@@ -106,6 +106,6 @@ pub fn transfer(
|
||||
|
||||
vec![
|
||||
AccountPostState::new(sender_post),
|
||||
AccountPostState::new_claimed_if_default(recipient_post),
|
||||
AccountPostState::new_claimed_if_default(recipient_post, Claim::Authorized),
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user