Decentralized Exchanges (DEXs) have become a cornerstone of the DeFi ecosystem, processing billions in daily trading volume. However, during our recent security research at FuzzingLabs we uncovered a subtle yet significant vulnerability pattern that affects multiple DEX implementations. This vulnerability allows malicious actors to effectively disable newly created liquidity pools through initialization parameter manipulation.
The pattern is particularly interesting because it stems from common architectural decisions rather than implementation errors. While auditing various DEX protocols, we discovered that this vulnerability manifests in different forms but always follows the same core pattern: the ability to “poison” a pool during its initialization phase by setting critical parameters to extreme values.
This blog post details the technical aspects of this vulnerability pattern, its impact on DeFi protocols, and presents concrete mitigation strategies for protocol developers. Our goal is to raise awareness about this design pattern vulnerability and help the DeFi ecosystem build more robust protocols.
The Raydium Concentrated Liquidity Market Maker (CLMM) implementation provided a clear example of how initialization parameter manipulation can lead to pool denial of service. This case study examines a vulnerability found in January 2024 that allowed attackers to render new pools inoperable by manipulating their activation timestamp.
The vulnerability resided in the pool initialization code of the Raydium CLMM program. The critical section of code responsible for pool creation looked like this:
pub struct CreatePool<'info> {
/// Initialize an account to store the pool state
#[account(
init,
seeds = [
POOL_SEED.as_bytes(),
amm_config.key().as_ref(),
token_mint_0.key().as_ref(),
token_mint_1.key().as_ref(),
],
bump,
payer = pool_creator,
space = PoolState::LEN
)]
pub pool_state: AccountLoader<'info, PoolState>,
// ... other accounts
}
pub fn create_pool(ctx: Context, sqrt_price_x64: u128, open_time: u64) -> Result<()> {
pool_state.initialize(
bump,
sqrt_price_x64,
open_time,// No validation on open_time
tick,
ctx.accounts.pool_creator.key(),
)?;
// ... remainder of initialization logic
}
The key vulnerability lay in the uniqueness of the pool_state for each token pair combination and the open_time parameter, which determined when the pool would become active for trading. This parameter was accepted without any bounds checking.
The vulnerability stemmed from several architectural decisions in the Raydium implementation:
First, the protocol used a PDA (Program Derived Address) system that enforced unique pool addresses based on token pair combinations. This meant only one pool could exist for a given token pair with specific parameters.
seeds = [
POOL_SEED.as_bytes(),
amm_config.key().as_ref(),
token_mint_0.key().as_ref(),
token_mint_1.key().as_ref(),
], // Pool address is derived from the tokens addresses
Second, the initialization function accepted the open_time parameter as a raw Unix timestamp without any validation against reasonable time bounds. There was no maximum limit on how far in the future this timestamp could be set.
pub fn create_pool(ctx: Context, sqrt_price_x64: u128, open_time: u64) -> Result<()> {
// No boundaries on `open_time`
}
Finally, once initialized, the pool’s opening time could not be modified, making any malicious initialization effectively permanent.
Here’s how an attacker could exploit this vulnerability:
Alternatively, one could also frontrun initialization transactions:
The exploitation of this vulnerability had several consequences for the Raydium ecosystem:
The affected token pair became unusable on the protocol until the specified open_time, which could be years or decades. Because the pool address was deterministic based on the token pair, no other pool could be created for these tokens.
Legitimate market makers and traders could not create any new trading pool.
The vulnerability could have been addressed through several possible changes to the protocol:
Liquidity pools in DeFi protocols are particularly vulnerable to Denial of Service (DOS) attacks during their initialization phase due to a common architectural pattern. This vulnerability stems from how pools are typically designed and deployed.
Most liquidity pool implementations follow these key architectural principles:
At the heart of these vulnerabilities lies a common pattern: the ability for malicious actors to “poison” new liquidity pools by frontrunning their initialization with deliberately harmful parameters. This attack vector is particularly interesting because it exploits the fundamental design of unique pool addresses in DeFi protocols.
This attack follows a precise pattern that takes advantage of the transaction ordering nature of blockchain systems. When a legitimate creator attempts to deploy a new liquidity pool, their transaction must first pass through the mempool. During this period, attackers can monitor pool initialization transactions and analyze their parameters.
Upon detecting a new pool creation, the attacker can craft their own initialization transaction with identical pool parameters but modify critical values to render the pool unusable. By submitting this transaction with higher gas fees or transaction priorities, they ensure their malicious initialization executes before the legitimate one.
Note that instead of performing a frontrun transaction it is possible in some cases to predict the token pairs that people will want to initialize and execute the malicious initialization ahead of time.
In order to trigger a DOS of the pool you can manipulate the parameters used in the initialization process. Depending on the architecture you may be able to:
Any of these malicious initial parameters will make the pool unusable.
The initialization DOS vulnerability pattern we’ve explored demonstrates how subtle architectural decisions in DeFi protocols can lead to significant security implications. While our example focused on a bug we found on Solana programs, this vulnerability pattern is not chain-specific. Similar initialization parameter manipulation attacks could affect any smart-contract, including on Ethereum, BSC, or other EVM-compatible chains.
At FuzzingLabs, our security research helped numerous protocols strengthen their implementations against these and other vulnerability patterns. Whether you’re developing on Solana, Ethereum, or other chains, proper security review is essential before deployment.
Patrick Ventuzelo / @Pat_Ventuzelo
Mathieu Troullier / @mathieu_t
Founded in 2021 and headquartered in Paris, FuzzingLabs is a cybersecurity startup specializing in vulnerability research, fuzzing, and blockchain security. We combine cutting-edge research with hands-on expertise to secure some of the most critical components in the blockchain ecosystem.
Contact us for an audit or long term partnership!
Cookie | Duration | Description |
---|---|---|
cookielawinfo-checkbox-analytics | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics". |
cookielawinfo-checkbox-functional | 11 months | The cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional". |
cookielawinfo-checkbox-necessary | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary". |
cookielawinfo-checkbox-others | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other. |
cookielawinfo-checkbox-performance | 11 months | This cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance". |
viewed_cookie_policy | 11 months | The cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data. |