> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nilemarkets.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Contract Addresses

> Per-chain contract addresses for all nine Nile Markets contracts on Ethereum Sepolia (chainId 11155111) and Arbitrum Sepolia (chainId 421614) — Protocol, Config, OracleModule, ModeController, RiskManager, MarginAccounts, PoolVault, PositionManager, SettlementEngine — with block explorer links and SDK loading patterns.

The same protocol is deployed on both testnets with identical contract bytecode and identical parameters.
Switch tabs to view per-chain addresses.

<Tabs>
  <Tab title="Ethereum Sepolia">
    chainId: `11155111` · Block explorer: [sepolia.etherscan.io](https://sepolia.etherscan.io)

    | Contract         | Address                                      | Description                                                              |
    | ---------------- | -------------------------------------------- | ------------------------------------------------------------------------ |
    | Protocol         | `0xC20E775e274314570DAa1d50a191750753F686dA` | Root registry for all contract addresses and role assignments            |
    | Config           | `0x8653f27FB34bF845c7C16Dca07DFf7A0cd2A6557` | Configurable parameters (margin factors, fee rates, tenors, risk caps)   |
    | OracleModule     | `0x1f78995b606CCF768E0a532Be8A1AB6eDf3Cd4D5` | Pyth spot prices + publisher-pushed forward prices with safeguards       |
    | ModeController   | `0x2b7775De7a4696f05D875BDE8f983303A3d49582` | Operating mode state machine (NORMAL / DEGRADED / REDUCE\_ONLY / PAUSED) |
    | RiskManager      | `0xd82515b62501F011DA2BaFA877B57f8713dc20Ee` | Per-position, per-account, and pool-level exposure caps and validation   |
    | MarginAccounts   | `0x12c310A5A5B5771459ff96979931CddE75A6D935` | Collateral deposits, margin locking, and PnL settlement                  |
    | PoolVault        | `0x61208f0337eE40278b0cbc55daEE7A37Fa180618` | ERC-4626 liquidity pool for LP deposits and share token management       |
    | PositionManager  | `0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd` | Position lifecycle: open, increase, reduce, close, margin management     |
    | SettlementEngine | `0x86f9339EC3Ca09aa51E1862911678C696eC09470` | Settlement at maturity, liquidation, and early termination processing    |
    | MockUSDC         | `0x319FeC6Cc374922A183A354a41E89b7A313EE547` | Test USDC token (6 decimals) with public `mint` faucet function          |

    **Start block**: `10391511` — used as the `startBlock` in the subgraph and event scanning.
  </Tab>

  <Tab title="Arbitrum Sepolia">
    chainId: `421614` · Block explorer: [sepolia.arbiscan.io](https://sepolia.arbiscan.io)

    Addresses are populated by the first deployment. Check `packages/contracts/deployments/arbitrumSepolia/addresses.json` after the operator runs `make deploy-contracts NETWORK=arbitrumSepolia` for the canonical values.

    | Contract         | Description                                                              |
    | ---------------- | ------------------------------------------------------------------------ |
    | Protocol         | Root registry for all contract addresses and role assignments            |
    | Config           | Configurable parameters (margin factors, fee rates, tenors, risk caps)   |
    | OracleModule     | Pyth spot prices + publisher-pushed forward prices with safeguards       |
    | ModeController   | Operating mode state machine (NORMAL / DEGRADED / REDUCE\_ONLY / PAUSED) |
    | RiskManager      | Per-position, per-account, and pool-level exposure caps and validation   |
    | MarginAccounts   | Collateral deposits, margin locking, and PnL settlement                  |
    | PoolVault        | ERC-4626 liquidity pool for LP deposits and share token management       |
    | PositionManager  | Position lifecycle: open, increase, reduce, close, margin management     |
    | SettlementEngine | Settlement at maturity, liquidation, and early termination processing    |
    | MockUSDC         | Test USDC token (6 decimals) with public `mint` faucet function          |
  </Tab>
</Tabs>

<Info>
  Bytecode is **identical** on both chains. Only the addresses, the Pyth contract that `OracleModule`
  wraps, and the per-chain `startBlock` differ.
</Info>

## External Dependencies

The protocol integrates with external infrastructure that is not operated by the Nile Markets team.
Pyth Network is deployed on every chain at a chain-specific address; price feed IDs are global.

| Dependency              | Identifier                                                           | Purpose                                                                                                                                                                                |
| ----------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pyth EUR/USD Price Feed | `0xa995d00bb36a63cef7fd2c287dc105fc8f3d93779f062f09551b0af3e81ec30b` | Real-time EUR/USD spot price used for fixing prices and oracle health checks                                                                                                           |
| Pyth USD/JPY Price Feed | `0xef2c98c804ba503c6a707e38be4dfbb16683775f195b091252bf24693042fd52` | Real-time USD/JPY spot price                                                                                                                                                           |
| Pyth Network            | [pyth.network](https://pyth.network/)                                | Decentralized oracle network providing the underlying price feed (per-chain contract address — see [Pyth EVM addresses](https://docs.pyth.network/price-feeds/contract-addresses/evm)) |

<Note>
  The Pyth price feed IDs are `bytes32` identifiers, not Ethereum addresses. They are used by the
  publisher service to fetch prices from the Pyth Hermes API and by the OracleModule to verify
  onchain price updates. The same feed IDs are used on every supported chain.
</Note>

## Block Explorer

Contracts are verified on each chain's block explorer.

<Tip>
  To view any contract, use the appropriate explorer base URL:

  * Ethereum Sepolia: `https://sepolia.etherscan.io/address/<CONTRACT_ADDRESS>`
  * Arbitrum Sepolia: `https://sepolia.arbiscan.io/address/<CONTRACT_ADDRESS>`

  For example, the Sepolia PositionManager:
  [https://sepolia.etherscan.io/address/0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd](https://sepolia.etherscan.io/address/0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd)
</Tip>

## Contract Architecture

The contracts are organized into shared infrastructure (singletons) and per-pool instances:

```
Protocol (Root Registry)
+-- Shared Infrastructure
|   +-- Config             -- All configurable parameters
|   +-- OracleModule       -- Pyth spot + publisher-pushed forwards
|   +-- ModeController     -- Operating mode state machine
|   +-- RiskManager        -- Risk caps and validation
+-- Pool 0 (USDC)
    +-- MarginAccounts     -- Collateral and margin management
    +-- PoolVault          -- ERC-4626 liquidity pool
    +-- PositionManager    -- Position lifecycle
    +-- SettlementEngine   -- Settlement, liquidation, termination
```

All contracts are **non-upgradeable** (no proxy pattern). Parameters are configurable via the Config
contract, but contract logic is immutable. Logic changes require a full redeployment.

## Loading Addresses in Code

### TypeScript (Frontend / SDK)

The frontend loads addresses from the deployment JSON file via the `getAddress` helper, which
resolves the correct address based on the connected chain ID:

```typescript theme={null}
import { getAddress } from "@/config/addresses";
import { useChainId } from "wagmi";
import { positionManagerAbi } from "@nile-markets/sdk";

const chainId = useChainId();
const positionManager = getAddress(chainId, "positionManager");
```

Address resolution by chain:

* Chain ID `11155111` (Ethereum Sepolia) loads from `deployments/sepolia/addresses.json`
* Chain ID `421614` (Arbitrum Sepolia) loads from `deployments/arbitrumSepolia/addresses.json`
* Chain ID `31337` (Anvil) loads from `deployments/anvil/addresses.json`

### TypeScript (Standalone / Node.js)

For scripts or services that do not use wagmi, reference addresses directly:

```typescript theme={null}
import { createPublicClient, http } from "viem";
import { sepolia } from "viem/chains";
import { poolVaultAbi } from "@nile-markets/sdk";

const client = createPublicClient({
  chain: sepolia,
  transport: http("YOUR_RPC_URL"),
});

const POOL_VAULT = "0x61208f0337eE40278b0cbc55daEE7A37Fa180618";

const totalAssets = await client.readContract({
  address: POOL_VAULT,
  abi: poolVaultAbi,
  functionName: "totalAssets",
});
```

### Rust (Keeper / Publisher)

Rust services receive contract addresses via environment variables or CLI arguments:

```rust theme={null}
use alloy::primitives::Address;
use fx_contracts::generated::settlement_engine::SettlementEngine;

let address: Address = std::env::var("SETTLEMENT_ENGINE_ADDRESS")
    .expect("SETTLEMENT_ENGINE_ADDRESS required")
    .parse()
    .expect("Invalid address");

let contract = SettlementEngine::new(address, &provider);
```

For the EUR/USD pair ID constant (pre-computed `keccak256("EUR/USD")`):

```rust theme={null}
use fx_contracts::EUR_USD_PAIR_ID;
let pair_id = EUR_USD_PAIR_ID;
```

### Subgraph

The subgraph references contract addresses in `subgraph.yaml` data sources:

```yaml theme={null}
dataSources:
  - kind: ethereum
    name: PositionManager
    source:
      address: "0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd"
      abi: PositionManager
      startBlock: 10391511
    mapping:
      # ...handler configuration
```

## Deployment JSON

The canonical source of truth for addresses is the deployment JSON file generated by the deploy
script:

```json theme={null}
{
  "config": "0x8653f27FB34bF845c7C16Dca07DFf7A0cd2A6557",
  "marginAccounts": "0x12c310A5A5B5771459ff96979931CddE75A6D935",
  "modeController": "0x2b7775De7a4696f05D875BDE8f983303A3d49582",
  "oracleModule": "0x1f78995b606CCF768E0a532Be8A1AB6eDf3Cd4D5",
  "poolVault": "0x61208f0337eE40278b0cbc55daEE7A37Fa180618",
  "positionManager": "0x8d81E9f1D0F0d1BdAAc0a91AFc2976522429A0cd",
  "protocol": "0xC20E775e274314570DAa1d50a191750753F686dA",
  "riskManager": "0xd82515b62501F011DA2BaFA877B57f8713dc20Ee",
  "settlementEngine": "0x86f9339EC3Ca09aa51E1862911678C696eC09470",
  "startBlock": 10391511,
  "usdc": "0x319FeC6Cc374922A183A354a41E89b7A313EE547"
}
```

<Tip>
  Contract addresses should never be stored in environment variables. They are always loaded from the
  deployment JSON file, which is generated by the deploy script and committed to the repository. This
  ensures a single source of truth that stays in sync across all consumers (frontend, subgraph, tests).
</Tip>
