> For the complete documentation index, see [llms.txt](https://docs.cork.tech/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cork.tech/developers/quick-start.md).

# Quick Start

This guide gets you from zero to reading Cork Protocol data and simulating a deposit on a local fork.

## Contract Addresses

Cork Phoenix uses deterministic CREATE2 deployment — all addresses are identical across Ethereum mainnet and supported chains.

| Contract         | Address                                      |
| ---------------- | -------------------------------------------- |
| CorkPoolManager  | `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC` |
| CorkAdapter      | `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407` |
| WhitelistManager | `0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE` |

## Find an Active Market

Every Cork Pool is identified by a MarketId. Fetch active markets from the API:

```bash
curl -s "https://api-phoenix.cork.tech/v1/pools/?chainId=1" | jq '.items[0] | {poolId, poolName, expiry}'
```

This returns a MarketId you can use in the examples below. You can also browse the full list at the [API interactive docs](https://api-phoenix.cork.tech/docs).

## Query Pool State

{% tabs %}
{% tab title="Foundry" %}
No setup required beyond [Foundry](https://book.getfoundry.sh/getting-started/installation). Query any pool directly with `cast`:

```bash
# Set your RPC endpoint and a MarketId from the API
export RPC_URL="https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"
export MARKET_ID="0xab4988fb673606b689a98dc06bdb3799c88a1300b6811421cd710aa8f86b702a"
export POOL_MANAGER="0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC"

# Get the swap rate (1 REF = rate/1e18 CA)
cast call $POOL_MANAGER \
  "swapRate(bytes32)(uint256)" $MARKET_ID \
  --rpc-url $RPC_URL

# Get pool balances (collateral, reference)
cast call $POOL_MANAGER \
  "assets(bytes32)(uint256,uint256)" $MARKET_ID \
  --rpc-url $RPC_URL

# Get cPT and cST token addresses
cast call $POOL_MANAGER \
  "shares(bytes32)(address,address)" $MARKET_ID \
  --rpc-url $RPC_URL
```

{% endtab %}

{% tab title="TypeScript" %}
Install dependencies:

```bash
npm install viem
```

Create `query-cork.ts`:

```typescript
import { createPublicClient, http, type Address } from 'viem'
import { mainnet } from 'viem/chains'

const client = createPublicClient({
  chain: mainnet,
  transport: http(), // uses default public RPC — replace with your own for production
})

const POOL_MANAGER: Address = '0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC'

// Fetch an active market from the API, or paste a known MarketId
const MARKET_ID = '0xab4988fb673606b689a98dc06bdb3799c88a1300b6811421cd710aa8f86b702a' as `0x${string}`

const poolManagerAbi = [
  {
    name: 'swapRate',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }],
    outputs: [{ name: 'rate', type: 'uint256' }],
  },
  {
    name: 'assets',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }],
    outputs: [
      { name: 'collateralAssets', type: 'uint256' },
      { name: 'referenceAssets', type: 'uint256' },
    ],
  },
  {
    name: 'shares',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }],
    outputs: [
      { name: 'principalToken', type: 'address' },
      { name: 'swapToken', type: 'address' },
    ],
  },
] as const

async function main() {
  const swapRate = await client.readContract({
    address: POOL_MANAGER,
    abi: poolManagerAbi,
    functionName: 'swapRate',
    args: [MARKET_ID],
  })
  console.log('Swap rate:', Number(swapRate) / 1e18)

  // Asset balances use the token's native decimals (e.g., 18 for sUSDe, 6 for vbUSDC)
  const [collateral, reference] = await client.readContract({
    address: POOL_MANAGER,
    abi: poolManagerAbi,
    functionName: 'assets',
    args: [MARKET_ID],
  })
  console.log('Collateral:', collateral)
  console.log('Reference:', reference)

  const [principalToken, swapToken] = await client.readContract({
    address: POOL_MANAGER,
    abi: poolManagerAbi,
    functionName: 'shares',
    args: [MARKET_ID],
  })
  console.log('cPT:', principalToken)
  console.log('cST:', swapToken)
}

main()
```

Run it:

```bash
npx tsx query-cork.ts
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
When you deposit Collateral Asset into a Cork Pool, you receive two tokens: a **Cork Principal Token (cPT)** representing your principal claim, and a **Cork Swap Token (cST)** representing your swap rights. See [Cork Principal Token](/core-concepts/principal-token.md) and [Cork Swap Token](/core-concepts/swap-token.md) for details.
{% endhint %}

## Simulate a Deposit

Fork mainnet locally and simulate a deposit without using real tokens.

{% tabs %}
{% tab title="Foundry" %}

### 1. Start a Local Fork

```bash
anvil --fork-url $RPC_URL
```

### 2. Run a Forge Script

Create `script/DepositExample.s.sol`:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Script, console} from "forge-std/Script.sol";

interface IERC20 {
    function approve(address spender, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

interface IPoolManager {
    function previewDeposit(bytes32 poolId, uint256 collateralAssetsIn) external view returns (uint256);
    function deposit(bytes32 poolId, uint256 collateralAssetsIn, address receiver) external returns (uint256);
    function shares(bytes32 poolId) external view returns (address, address);
    function swapRate(bytes32 poolId) external view returns (uint256);
}

interface IWhitelistManager {
    function isWhitelisted(bytes32 poolId, address account) external view returns (bool);
}

contract DepositExample is Script {
    address constant POOL_MANAGER = 0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC;
    address constant WHITELIST_MANAGER = 0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE;

    // sUSDe (Collateral Asset for the example market)
    address constant SUSDE = 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497;

    function run() external {
        // Replace with a MarketId from the API
        bytes32 marketId = 0xab4988fb673606b689a98dc06bdb3799c88a1300b6811421cd710aa8f86b702a;

        // Use a test address — Anvil's default account
        address depositor = 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266;

        // Deal 100 sUSDe to the depositor
        uint256 depositAmount = 100e18;
        deal(SUSDE, depositor, depositAmount);

        // Check whitelist status
        bool whitelisted = IWhitelistManager(WHITELIST_MANAGER).isWhitelisted(marketId, depositor);
        console.log("Whitelisted:", whitelisted);

        // If not whitelisted, the deposit will revert.
        // For testing, you can disable the whitelist or add the address via DefaultCorkController.
        if (!whitelisted) {
            console.log("Address not whitelisted — skipping deposit");
            return;
        }

        // Check swap rate
        uint256 rate = IPoolManager(POOL_MANAGER).swapRate(marketId);
        console.log("Swap rate:", rate);

        // Preview deposit
        uint256 expectedShares = IPoolManager(POOL_MANAGER).previewDeposit(marketId, depositAmount);
        console.log("Expected cPT + cST:", expectedShares);

        // Execute deposit
        vm.startBroadcast(depositor);
        IERC20(SUSDE).approve(POOL_MANAGER, depositAmount);
        uint256 sharesOut = IPoolManager(POOL_MANAGER).deposit(marketId, depositAmount, depositor);
        vm.stopBroadcast();
        console.log("Shares received:", sharesOut);

        // Check cPT and cST balances (both use 18 decimals)
        (address cpt, address cst) = IPoolManager(POOL_MANAGER).shares(marketId);
        console.log("cPT balance:", IERC20(cpt).balanceOf(depositor));
        console.log("cST balance:", IERC20(cst).balanceOf(depositor));
    }
}
```

Run it against your local fork:

```bash
forge script script/DepositExample.s.sol --fork-url http://127.0.0.1:8545 --broadcast
```

{% hint style="info" %}
The `deal` cheatcode sets token balances directly — no need to source tokens from an external account. This avoids dependencies on specific whitelisted addresses or funded accounts.
{% endhint %}
{% endtab %}

{% tab title="TypeScript" %}

### 1. Start a Local Fork

```bash
anvil --fork-url $YOUR_RPC_URL
```

### 2. Run the Deposit Script

Install dependencies:

```bash
npm install viem tsx
```

Create `deposit-fork.ts`:

```typescript
import {
  createPublicClient,
  createWalletClient,
  http,
  parseUnits,
  encodeFunctionData,
  type Address,
  type Hex,
} from 'viem'
import { foundry } from 'viem/chains'

const transport = http('http://127.0.0.1:8545')
const publicClient = createPublicClient({ chain: foundry, transport })
const walletClient = createWalletClient({ chain: foundry, transport })

const POOL_MANAGER: Address = '0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC'
const WHITELIST_MANAGER: Address = '0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE'
const SUSDE: Address = '0x9D39A5DE30e57443BfF2A8307A4256c8797A3497'

// Fetch an active MarketId from the API, or paste one here
const MARKET_ID: Hex = '0xab4988fb673606b689a98dc06bdb3799c88a1300b6811421cd710aa8f86b702a'

// Use Anvil's default funded account
const DEPOSITOR: Address = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'

const erc20Abi = [
  {
    name: 'approve',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [{ name: 'spender', type: 'address' }, { name: 'amount', type: 'uint256' }],
    outputs: [{ type: 'bool' }],
  },
  {
    name: 'balanceOf',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'account', type: 'address' }],
    outputs: [{ type: 'uint256' }],
  },
] as const

const poolManagerAbi = [
  {
    name: 'shares',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }],
    outputs: [{ name: 'principalToken', type: 'address' }, { name: 'swapToken', type: 'address' }],
  },
  {
    name: 'previewDeposit',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }, { name: 'collateralAssetsIn', type: 'uint256' }],
    outputs: [{ name: 'cptAndCstSharesOut', type: 'uint256' }],
  },
  {
    name: 'deposit',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [
      { name: 'poolId', type: 'bytes32' },
      { name: 'collateralAssetsIn', type: 'uint256' },
      { name: 'receiver', type: 'address' },
    ],
    outputs: [{ name: 'cptAndCstSharesOut', type: 'uint256' }],
  },
] as const

const whitelistAbi = [
  {
    name: 'isWhitelisted',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'poolId', type: 'bytes32' }, { name: 'account', type: 'address' }],
    outputs: [{ type: 'bool' }],
  },
] as const

async function main() {
  const depositAmount = parseUnits('100', 18) // 100 sUSDe

  // Deal tokens to the depositor using Anvil's cheatcode
  await publicClient.request({
    method: 'anvil_impersonateAccount' as 'eth_chainId',
    params: [DEPOSITOR],
  })

  // Check whitelist
  const isWhitelisted = await publicClient.readContract({
    address: WHITELIST_MANAGER,
    abi: whitelistAbi,
    functionName: 'isWhitelisted',
    args: [MARKET_ID, DEPOSITOR],
  })
  console.log('Whitelisted:', isWhitelisted)

  if (!isWhitelisted) {
    console.log('Address not whitelisted — deposit would revert')
    return
  }

  // Preview
  const expectedShares = await publicClient.readContract({
    address: POOL_MANAGER,
    abi: poolManagerAbi,
    functionName: 'previewDeposit',
    args: [MARKET_ID, depositAmount],
  })
  // cPT and cST always use 18 decimals, regardless of the underlying token's decimals
  console.log('Expected cPT + cST:', Number(expectedShares) / 1e18)

  // Approve
  await walletClient.sendTransaction({
    account: DEPOSITOR,
    to: SUSDE,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: 'approve',
      args: [POOL_MANAGER, depositAmount],
    }),
  })

  // Deposit
  const txHash = await walletClient.sendTransaction({
    account: DEPOSITOR,
    to: POOL_MANAGER,
    data: encodeFunctionData({
      abi: poolManagerAbi,
      functionName: 'deposit',
      args: [MARKET_ID, depositAmount, DEPOSITOR],
    }),
  })
  console.log('Deposit tx:', txHash)

  // Check balances
  const [cptAddress, cstAddress] = await publicClient.readContract({
    address: POOL_MANAGER,
    abi: poolManagerAbi,
    functionName: 'shares',
    args: [MARKET_ID],
  })

  const cptBalance = await publicClient.readContract({
    address: cptAddress,
    abi: erc20Abi,
    functionName: 'balanceOf',
    args: [DEPOSITOR],
  })
  const cstBalance = await publicClient.readContract({
    address: cstAddress,
    abi: erc20Abi,
    functionName: 'balanceOf',
    args: [DEPOSITOR],
  })

  console.log('cPT balance:', Number(cptBalance) / 1e18)
  console.log('cST balance:', Number(cstBalance) / 1e18)
}

main()
```

Run it:

```bash
npx tsx deposit-fork.ts
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Whitelist:** Some Cork markets require addresses to be whitelisted before depositing. The examples above check whitelist status before attempting a deposit. For testing on a fork, you can disable the whitelist by impersonating the DefaultCorkController admin.
{% endhint %}

{% hint style="warning" %}
**Use CorkAdapter for production.** The examples above call CorkPoolManager directly for simplicity. In production, use [CorkAdapter](/developers/contract-reference/cork-adapter.md) — it wraps the same operations with slippage protection and deadline checks.
{% endhint %}

## Production Integration

**Solidity integrators:** Add Cork as a Foundry dependency:

```bash
forge install cork-technology/phoenix
```

Then import interfaces directly:

```solidity
import {IPoolManager, MarketId, Market} from "contracts/interfaces/IPoolManager.sol";
import {ICorkAdapter} from "contracts/interfaces/ICorkAdapter.sol";
```

**TypeScript integrators:** Use [viem](https://viem.sh) with the ABI snippets shown above, or install the published package:

```bash
npm install @cork-technology/phoenix
```

## Key Gotchas

{% hint style="warning" %}
**MarketId computation** — A MarketId is `keccak256(abi.encode(Market))` where Market contains 8 fields (collateralAsset, referenceAsset, expiryTimestamp, rateMin, rateMax, rateChangePerDayMax, rateChangeCapacityMax, rateOracle). It is not a simple hash of two addresses. See [CorkPoolManager > Key Concepts](/developers/contract-reference/cork-pool-manager.md#key-concepts) for the full computation.
{% endhint %}

{% hint style="info" %}
**18-decimal shares** — All Cork Principal Token (cPT) and Cork Swap Token (cST) amounts use 18 decimals, regardless of the underlying token's decimals. A market with 6-decimal USDC as Collateral Asset still produces 18-decimal cPT and cST.
{% endhint %}

## Next Steps

* [CorkAdapter](/developers/contract-reference/cork-adapter.md) — slippage-protected write operations for production use
* [CorkPoolManager](/developers/contract-reference/cork-pool-manager.md) — full query and operation reference
* [API Reference](/developers/api-reference.md) — historical data, market discovery, and limit orders


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.cork.tech/developers/quick-start.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
