Skip to content

[SECURITY] Paloma ETF Trader Contact Security Fixes #3051

@taariq

Description

@taariq

Palomadex Trader Contract - Security Vulnerability Report

Executive Summary

This security audit identified multiple critical and high-severity vulnerabilities in the Palomadex Trader Contract that could lead to permanent fund loss, contract lockout, and financial exploitation. Immediate fixes are required before any production deployment.

Critical Vulnerabilities

1. Contract Permanent Lockout (Critical)

Location: remove_owner function in src/contract.rs
Issue: The contract can be permanently locked if all owners are removed.

// Current code has no protection against removing the last owner
pub fn remove_owner(
    deps: DepsMut,
    info: MessageInfo,
    owner: String,
) -> Result<Response<PalomaMsg>, ContractError> {
    let mut state = STATE.load(deps.storage)?;
    // ... validation code ...
    state.owners.retain(|x| x != owner);  // No check if this is the last owner
    STATE.save(deps.storage, &state)?;
    Ok(Response::new().add_attribute("action", "update_config"))
}

Fix: Add validation to prevent removing the last owner:

if state.owners.len() <= 1 {
    return Err(ContractError::CannotRemoveLastOwner {});
}

2. LP Balance Tracking Inconsistency (Critical)

Location: remove_liquidity function
Issue: User's LP balance is deducted before actual withdrawal, creating permanent inconsistency if withdrawal fails.

// Balance is deducted first
LP_BALANCES.update(
    deps.storage,
    (receiver.clone(), lp_token.to_string()),
    |balance| -> StdResult<_> { Ok(balance.unwrap_or_default() - amount) },
)?;
// Then withdrawal happens in submessage - if this fails, balance is already reduced
let payload = to_json_binary(&(coins, receiver, chain_id, lp_token.to_string()))?;

Fix: Only update balances after successful withdrawal in the reply handler.

3. Automatic Balance Manipulation (Critical)

Location: check_padex_diff reply handler
Issue: Automatically adjusts user balances based on contract's PADEX balance changes without validation.

pub fn check_padex_diff(
    deps: DepsMut,
    payload: Binary,
) -> Result<Response<PalomaMsg>, ContractError> {
    let (user, padex_balance): (String, Coin) = from_json(payload)?;
    let new_balance = deps.querier.query_balance(
        deps.api.addr_validate(user.as_str())?,  // ❌ WRONG! Should query contract address
        padex_balance.denom.clone(),
    )?;
    // Automatically adjusts user balance based on any difference
    if new_balance.amount > padex_balance.amount {
        let diff_balance = new_balance.amount - padex_balance.amount;
        LP_BALANCES.update(...)  // ❌ No validation this is legitimate
    }
}

Exploitation: Attacker could manipulate contract's PADEX balance to steal funds from other users.

Fix: Remove automatic balance adjustment or add proper validation and access controls.

4. Unlimited Fee Extraction (Critical)

Location: update_service_fee, update_gas_fee functions
Issue: Owners can set unlimited fees without bounds checking.

// No validation on fee amounts
pub fn update_service_fee(
    deps: DepsMut,
    info: MessageInfo,
    chain_id: String,
    new_service_fee: Uint256,  // ❌ No bounds checking
) -> Result<Response<PalomaMsg>, ContractError>

Fix: Add maximum fee limits:

const MAX_SERVICE_FEE: Uint256 = Uint256::from(1000000000000000000u128); // 1 ETH max
if new_service_fee > MAX_SERVICE_FEE {
    return Err(ContractError::FeeTooHigh {});
}

High Severity Vulnerabilities

5. Cross-chain Parameter Validation Missing (High)

Location: Multiple functions (send_to_evm, send_token, etc.)
Issue: No validation of target chain addresses, amounts, or chain IDs.

// No validation of recipient address format for target chain
pub fn send_to_evm(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    chain_id: String,      // ❌ Not validated
    amounts: Vec<String>,  // ❌ Not validated - could be malformed
    recipient: String,     // ❌ Not validated for target chain format
) -> Result<Response<PalomaMsg>, ContractError>

Fix: Add comprehensive validation:

// Validate chain ID is supported
if !SUPPORTED_CHAINS.contains(&chain_id) {
    return Err(ContractError::UnsupportedChain {});
}

// Validate recipient address format for target chain
if chain_id.starts_with("ethereum") && !is_valid_eth_address(&recipient) {
    return Err(ContractError::InvalidRecipientAddress {});
}

6. Nonce Replay Protection Issues (High)

Location: send_token function
Issue: Nonce is marked as used even if target chain transaction fails.

// Nonce is updated regardless of target chain success
MESSAGE_TIMESTAMP.save(
    deps.storage,
    (chain_id.clone(), nonce.to_string()),
    &env.block.time,
)?;

Fix: Only update nonce after confirmed target chain success or implement proper retry logic.

7. Mathematical Calculation Vulnerabilities (High)

Location: calculate_swap_amount function
Issue: Uses .unwrap() which can panic and has no bounds checking.

fn calculate_swap_amount(input_amount: Uint128, reserve_in: Uint128, fee_bps: u16) -> Uint128 {
    let receive_rate = Decimal256::from_ratio(10000 - fee_bps, 10000u16);
    // ... complex calculation ...
    .unwrap()  // ❌ Can panic
    .try_into()
    .unwrap()  // ❌ Can panic
}

Fix: Replace .unwrap() with proper error handling and add input validation.

8. State Consistency Issues (High)

Location: Multiple functions with external calls
Issue: Internal state updated before external calls complete.

Fix: Use the check-effects-interactions pattern and only update state after successful external calls.

Medium Severity Vulnerabilities

9. Missing Input Validation (Medium)

Issues:

  • String inputs not validated for length or format
  • Numeric inputs not checked for reasonable bounds
  • Address validation inconsistent across functions

10. Potential DoS Attacks (Medium)

Location: add_owner function
Issue: Unbounded array growth could cause gas exhaustion.

// No limit on number of owners
for owner in owners.iter() {
    let owner = deps.api.addr_validate(owner)?;
    if !state.owners.iter().any(|x| x == owner) {  // ❌ O(n) operation in loop
        state.owners.push(owner);
    }
}

Fix: Add maximum owner limit (e.g., 10 owners).

11. External Contract Interface Not Validated (Medium)

Issue: Contract accepts incentivizer and other contract addresses without validating they implement expected interfaces.

Fix: Add interface validation during setup.

12. Slippage Protection Not Enforced (Medium)

Location: exchange function
Issue: Slippage protection is optional and not enforced.

Fix: Make slippage protection mandatory or set reasonable defaults.

Low Severity Issues

13. Inconsistent Error Handling (Low)

Issue: Some functions use assert! while others use proper error types.

14. Missing Edge Case Validations (Low)

Issue: No validation for zero amounts, empty arrays, etc.

15. Front-running Vulnerabilities (Low)

Issue: MEV opportunities in cross-chain operations.

Recommendations

Immediate Actions Required:

  1. Fix critical vulnerabilities before any deployment
  2. Add comprehensive input validation to all public functions
  3. Implement proper error handling instead of panics
  4. Add bounds checking to all fee and amount parameters
  5. Fix balance tracking logic to maintain consistency

Security Improvements:

  1. Implement circuit breakers for emergency stops
  2. Add comprehensive logging for audit trails
  3. Implement multi-signature for critical operations
  4. Add time locks for parameter changes
  5. Implement slashing for malicious behavior

Testing Requirements:

  1. Unit tests for all mathematical calculations
  2. Integration tests for cross-chain operations
  3. Fuzzing tests for input validation
  4. Security tests for access control
  5. Edge case tests for boundary conditions

Deployment Recommendations:

  1. Staged rollout with limited functionality
  2. Monitoring systems for unusual activity
  3. Emergency response procedures
  4. Regular security audits
  5. Bug bounty program

Conclusion

The Palomadex Trader Contract contains multiple severe security vulnerabilities that must be addressed before production deployment. The combination of access control issues, balance tracking inconsistencies, and lack of input validation creates significant risk for fund loss and contract exploitation.

Recommendation: DO NOT DEPLOY until all critical and high-severity vulnerabilities are resolved and the contract undergoes additional security review.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions