PredMart > Documentation > Security

Security

PredMart is designed with a defense-in-depth security model. This page provides a comprehensive overview of the protocol's security architecture, covering the independent third-party audit, smart contract security, access control, the timelock governance system, oracle integrity, emergency mechanisms, and the upgrade process. Understanding these security measures is essential for users who want to evaluate the trust assumptions of the protocol.


Security Audit

PredMart's smart contracts have been independently audited by Hashlock, an established Web3 security firm. The full report — covering the audit scope, the findings, and how each was resolved — is publicly available:

Read the Hashlock audit report

We encourage you to read the report itself rather than relying on the auditor's name alone. It's also available as a direct PDF.


Non-Custodial Design

PredMart's most fundamental security property is its non-custodial architecture. At no point does the PredMart team, company, or any individual have direct access to user funds:

All fund movements are governed by the smart contract's immutable logic. The only entity that can move funds is the contract itself, and it only does so according to its programmed rules.

What This Means for Users


Smart Contract Architecture

Proxy Pattern (UUPS)

PredMart's lending pool uses the UUPS (Universal Upgradeable Proxy Standard) proxy pattern. This means the contract logic can be upgraded to fix bugs or add features, while the state (balances, positions, parameters) is preserved.

The proxy architecture has two components: - Proxy contract: Holds all state (storage) and delegates calls to the implementation - Implementation contract: Contains the actual logic

When an upgrade occurs, only the implementation address changes — the proxy address and all stored data remain the same.

Upgrade Process

Contract upgrades are protected by a timelocked proposal system:

  1. Proposal: The admin calls proposeUpgrade(newImplementation) — this logs the new implementation address and starts the timelock countdown
  2. Waiting period: The timelock delay must pass (the exact duration is set by the admin via activateTimelock())
  3. Execution: After the delay, the admin calls upgradeToAndCall() on the UUPS proxy to switch to the new implementation
  4. Cancellation: At any time before execution, the admin can call cancelUpgrade() to abort

The timelocked upgrade ensures that users have advance notice before any contract logic changes take effect. If a proposed upgrade is concerning, users can withdraw their funds during the waiting period.

Timelock Ratchet

The timelock mechanism has an important safety feature: the timelock can only be increased, never decreased. The activateTimelock(delay) function requires that the new delay is at least as long as the current delay. This prevents an admin from reducing the timelock to near-zero and pushing through a surprise upgrade.

Active Timelock

The timelock is active. All timelocked operations (oracle changes, LTV parameter updates, contract upgrades) require a mandatory waiting period before they can be executed. Users can monitor for *Proposed events and withdraw their funds during this window if they disagree. The current delay is published in Protocol Constants.


Access Control

Admin Role

The admin is a single Ethereum address that has authority over protocol parameters. The admin can:

Without timelock (immediate): - setPaused(bool) — Pause or unpause the protocol (emergency use) - withdrawReserves(amount) — Withdraw protocol fee revenue - setPoolCapBps(newCap) — Adjust the per-token borrow cap - transferAdmin(newAdmin) — Transfer admin rights to another address

With timelock (delayed): - proposeOracle(newOracle)executeOracle() — Change the oracle signing address - proposeAnchors(prices, ltvs)executeAnchors() — Change the LTV parameters - proposeUpgrade(newImpl) → upgrade — Change the contract implementation

What the Admin Cannot Do

Even with admin access, the following actions are impossible: - Transfer user funds directly (USDC or collateral) - Modify individual user positions or balances - Override the interest rate model calculations - Bypass health factor checks for liquidation - Force a borrow or withdrawal on behalf of a user - Access private keys or user signatures

Relayer Role

The relayer is a separate address authorized to execute borrow, withdrawal, and leverage operations: - Submit borrow transactions (with oracle-signed price data and user signatures) - Submit withdrawal transactions (with oracle-signed price data and user signatures) - Submit leverage transactions (with oracle-signed price data and user signatures)

The relayer cannot: - Borrow on behalf of a user without their signature - Withdraw collateral without the user's signature - Execute leverage without the user's signature - Redirect borrowed USDC to any address other than the user's signed allowedFrom address - Access or transfer funds not involved in a legitimate operation - Modify protocol parameters

Liquidator Role

The liquidator is a dedicated address authorized specifically for liquidation operations: - Execute liquidations (with oracle-signed price data) - Seize and sell collateral from unhealthy positions

The liquidator is separate from the relayer to ensure liquidations can operate independently and remain functional even if other backend services experience issues. The liquidator cannot perform borrow, withdrawal, or leverage operations.

Meta-Transaction Security

All borrow, withdraw, and leverage operations use EIP-712 typed structured data for signing. This provides several security benefits: - Human-readable signing prompts in wallets - Domain separation prevents cross-protocol replay - Typed data prevents signature malleability attacks

Nonce Separation

PredMart uses separate nonces for each operation type (borrow, withdraw, leverage). This prevents cross-operation replay attacks — a signed borrow intent cannot be replayed as a withdraw or leverage operation, even if nonce values coincidentally match.

allowedFrom Protection (Leverage)

For leverage operations, the user signs a LeverageAuth message that includes an allowedFrom field — the address (typically their Gnosis Safe) where borrowed USDC must be sent. The smart contract enforces this constraint, preventing the relayer from redirecting funds to any other address. This is a critical non-custodial safeguard.

Admin Transfer

The admin address can be transferred via transferAdmin(newAdmin). This is an immediate operation (no timelock) because the timelock is already protecting the sensitive operations that the admin can perform. If the admin key is compromised, the ability to quickly transfer to a new address is a security benefit.


Oracle Security

The Oracle's Role

PredMart's oracle is a backend service that signs price and resolution data. The smart contract only accepts data signed by the oracle's authorized address. This prevents users from submitting fabricated price data.

Price Data Security

Every borrow, withdrawal, and liquidation includes oracle-signed price data containing: - chainId — Prevents cross-chain replay - pool — The lending pool address (prevents use with other contracts) - tokenId — The specific token being priced - price — The oracle price - timestamp — When the price was fetched - maxBorrow — The per-market borrow cap

The smart contract verifies: - The signature is from the authorized oracle address - The timestamp is recent (freshness enforced on-chain) - The price is between 0 and 1 (exclusive)

Resolution Data Security

Market resolution data contains: - chainId, pool, tokenId — Same scoping as price data - won — Whether the token is the winning outcome - timestamp — When the resolution was determined

The contract verifies: - Valid oracle signature - Timestamp is sufficiently recent

Oracle Key Rotation

If the oracle key needs to be changed (e.g., suspected compromise), the admin can propose a new oracle address through the timelocked proposeOracle()executeOracle() flow. This ensures users have notice before the oracle changes.

Trust Assumption

The oracle is a centralized trust point in PredMart's architecture. Users must trust that: - The oracle reports accurate prices from Polymarket's CLOB - The oracle does not selectively delay or withhold price updates - The oracle's private key is properly secured

PredMart mitigates this trust assumption through: - Freshness checks (prices must be recent to be accepted) - Price sanity checks (must be within valid range) - Transparent oracle operations (all signed data is visible on-chain) - Timelocked oracle key rotation (users can react if the oracle changes)


Emergency Mechanisms

Protocol Pause

The admin can pause the protocol at any time via setPaused(true). When paused:

Liquidations are designed to work even when the protocol is paused. This ensures unhealthy positions can always be closed to protect lenders, regardless of protocol state.

The pause is designed to protect the protocol during: - Discovery of a smart contract vulnerability - External events that could compromise price oracle integrity - Other emergency situations

The admin can unpause via setPaused(false) when the situation is resolved.

Auto-Monitoring

PredMart's infrastructure is monitored continuously and can trigger the emergency pause if conditions threaten lending safety. Manual admin pauses are always respected. Liquidations remain available even while paused (see above).


Key Security Properties Summary

Property Implementation Trust Assumption
Independent audit Hashlock smart-contract audit (report) Auditor's review is thorough
Funds custody Smart contract Code is correct
Price integrity Oracle signatures + freshness checks Oracle reports accurate prices
User authorization EIP-712 signatures with nonce separation User controls their private key
Leverage safety allowedFrom constraint in LeverageAuth Relayer cannot redirect USDC
Upgrade safety UUPS + timelock + one-way ratchet Admin doesn't act maliciously during timelock
Liquidation speed Continuous monitoring with redundant paths Backend infrastructure is operational
Concentration limits Pool cap (5%) + per-market liquidity cap Limits are appropriately calibrated
Emergency response Pause Admin can respond to emergencies
Parameter changes Timelock governance Users can exit during waiting period

Recommendations for Users


Next Steps