# Core/Periphery Design Pattern for Immutable Protocols

For teams that decide **not** to use upgradeable contracts (see the [gradual immutability path](https://github.com/optimumsec/the-complete-guide-to-securing-web3-projects/blob/main/design/gradual-immutability-path.md)), the **core/periphery split** is a practical design choice that can minimize security issues while still allowing controlled changes of functionality.

## What Is the Core/Periphery Split?

The **core** is the immutable, minimal set of contracts that define protocol-critical logic and invariants. The **periphery** is the replaceable layer that handles user interactions, UX improvements, and convenience features.

### Core

* Immutable once deployed.
* Holds critical state and enforces protocol-level invariants.
* Example: Uniswap V2/V3 Pool contracts (AMM math, reserves, invariant checks).

### Periphery

* Can be re-deployed and versioned over time.
* Abstracts away complexity and adds features like batching, multicall, safer UX.
* Example: Uniswap Router, NonfungiblePositionManager.

## Why Use This Pattern?

* **Security:** Core stays locked down, surface area minimized.
* **Flexibility:** Teams can adapt UX, improve efficiency, or patch integration bugs without touching core.
* **Clarity:** Easier to communicate security guarantees: "The pool logic is immutable. Routers can change."

## Upgrade Strategy Without Proxies

Even if core is immutable, periphery contracts can evolve. Typical approaches include:

* **Versioned Routers:** Deploy new routers with improved logic; users migrate voluntarily.
* **Registries:** Maintain a registry contract pointing to the latest periphery; frontends can read from it.
* **Migrations:** Encourage/force users to migrate state from old periphery to new periphery.

## Security Model

* **Core**: must be fully audited, formally verified if possible, and designed for immutability.
* **Periphery**: can be updated, but still requires review since it can influence user behavior.
* **Interaction**: Core contracts should never trust periphery; only enforce strict invariants.

## Common Patterns

* **Router → Pool Calls:** Router bundles user actions and calls into pools.
* **Callback Interfaces:** Core pools define strict callback requirements, which routers must satisfy.
* **Position Managers:** Higher-level contracts for abstracting LP positions.
* **Fee Hooks / Incentives:** Kept in periphery to avoid contaminating invariant logic.

## Pitfalls

* **Too Much in Periphery:** If periphery enforces invariants instead of core, security assumptions break.
* **Silent Upgrades:** Replacing periphery without notice can create governance or trust issues.
* **Registry Risks:** If the registry is compromised, users may be routed to malicious periphery contracts.

## Example: Minimal Core/Periphery Split

```solidity
// Core: immutable pool
contract Pool {
    uint112 reserve0;
    uint112 reserve1;

    function swap(uint amount0Out, uint amount1Out) external {
        // Invariant: x * y >= k
        require(amount0Out == 0 || amount1Out == 0, "Only one side out");
        // ...
    }
}

// Periphery: router that interacts with core
contract Router {
    function swapExactTokensForTokens(...) external {
        // Handle approvals, slippage checks, path routing
        Pool(pool).swap(...);
    }
}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.optimumsec.xyz/design/core-periphery-design.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
