# What is Cork?

**TL;DR**\
Cork is a programmable risk layer for onchain assets such as vault tokens, yield-bearing stablecoins, and liquid (re)staking tokens. Cork's core primitive enables asset managers and issuers to spin up custom swap markets that enhance redemption liquidity, risk transparency, and market confidence for their onchain assets. Backed by a16z CSX, OrangeDAO, Road Capital, BitGo, G-20, and Steakhouse Financial, Cork is building the risk infrastructure needed to bring institutional capital into onchain credit markets.

***

## How Cork Works

Each **Cork Pool** pairs a [Collateral Asset](/core-concepts/collateral-asset) (CA) — a liquid, yield-bearing asset like sUSDS or wstETH — with a [Reference Asset](/core-concepts/reference-asset) (REF) — the asset whose risk is being managed, such as a vault token or RWA.

When a liquidity provider deposits the Collateral Asset, the pool mints two tokens:

* [**Cork Principal Token**](/core-concepts/principal-token) **(cPT)**: Represents the depositor's principal claim. At expiry, cPT holders redeem their proportional share of whatever remains in the pool.
* [**Cork Swap Token**](/core-concepts/swap-token) **(cST)**: Grants the right to exercise — exchange REF + cST for CA before expiry. This is the coverage instrument.

$$
Collateral\ Asset \rightarrow Cork\ Principal\ Token + Cork\ Swap\ Token
$$

The cPT holder earns yield (from the Collateral Asset and from selling cST at a premium). The cST holder gets guaranteed redemption liquidity — regardless of market conditions, they can always exchange their Reference Asset for the Collateral Asset through the Cork Pool.

Before expiry, cPT + cST can always be converted back to the original Collateral Asset:

$$
Cork\ Principal\ Token + Cork\ Swap\ Token = Collateral\ Asset
$$

***

## What Cork Enables

Cork Pools serve as a flexible primitive for managing onchain risk. Key applications include:

* **Liquidity buffers** — Instant liquidity for vaults and bridges with high utilization rates or withdrawal delays
* **Duration coverage** — Instant exit for assets with long redemption windows (RWAs with 40+ day queues)
* **Risk hedging** — Coverage against value loss for stablecoins, LSTs, LRTs, and vault tokens
* **Peg stability** — Guaranteed redemption liquidity strengthens issuer peg resilience
* **Protected loops** — Cork Pools enable looping vaults to self-liquidate atomically

See [Target Assets & Use Cases](/core-concepts/target-assets-and-use-cases) for detailed examples.

***

## Why Tokenized Risk?

As onchain adoption accelerates and institutional capital enters the space, risk infrastructure is emerging as a foundational requirement. As of early 2026, the stablecoin market has more than doubled since early 2024 (from $130B to over $300B), while tokenized real-world assets have surged from $1B in 2021 to $35B (source: RWA.xyz). In 2025, tokenization entered mainstream finance with Nasdaq approving trading of tokenized stocks and ETFs.

Yet robust tools for identifying, pricing, and transferring risk onchain remain underdeveloped. Events like the Terra–Luna failure ($40B+ vaporized, triggering contagion across major institutions) and the October 2025 liquidation event (when multiple pegged assets traded below parity on centralized venues) demonstrated that risk management cannot be an afterthought.

For institutional players to meaningfully participate in DeFi, and for the tokenization of RWAs, credit, and stablecoins to scale, onchain finance needs programmable, transparent, and composable risk primitives. Cork is building that infrastructure — making onchain risk explicit and tradable.


# Cork Pool

The core primitive — how Cork Pools work, the dual token system, exercise and repurchase mechanics

The foundational component of Cork Protocol is the `Cork Pool`, which is the mechanism around which our markets are built. It works as follows.

Each Cork Pool is built around an asset pair:

`Collateral Asset` or `CA` serves as collateral which swaps can be exercised against. It typically refers to highly liquid, low risk and well-established assets, such as Ether, USDC, or DAI. To improve capital efficiency it may also include derivatives or yield-bearing assets like sDAI or stETH.

`Reference Asset` or `REF` is designed to track or maintain parity with the Collateral Asset. The Reference Asset will generally have a different liquidity or risk profile, and may at times deviate in price from the Collateral Asset.

The Cork Pool can receive deposits of Collateral Asset where it is locked and mint two tokens that are returned to the depositor:

`Cork Principal Token` or `cPT`: Holders of the Cork Principal Token take on the potential risk in exchange for the opportunity to earn a “risk premium" by selling their Cork Swap Tokens. These investors are exposed to the possibility that the Reference Asset will lose value relative to the Collateral Asset but stand to benefit if swaps are not exercised.

`Cork Swap Token` or `cST` which is a swap token that allow a user to before it’s expiry make the following exchange:

$$
Cork\ Swap \ Token + Reference\ Asset = Collateral\ Asset
$$

The holder of the Cork Swap Token stands to profit in a potential liquidity crisis and can use the exposure to fully hedge the risk of a Reference Asset position.

Furthermore, the Cork Principal Token + Cork Swap Token can before the expiry always be converted back to the Collateral Asset 1:1.

$$
Cork \ Principal\ Token + Cork\ Swap \ Token = Collateral\ Asset
$$

**Mint Mechanism**: The Collateral Asset is deposited and used to mint the Cork Principal Token and Cork Swap Token that is returned to depositor. In the below diagram the flow can be seen with Eth as the Collateral Asset.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FbY4ZYHqUsTcIefX8q3OB%2Fpsm1.webp?alt=media&amp;token=f8284dd7-d8ee-442e-a2b3-65171033cb6a" alt=""><figcaption></figcaption></figure>

#### **Exchange Rate**

Most assets relevant to Cork accrue yield into the token value, for example Lido steth is a rebasing token but most of the liquidity and DeFi integrations for steth are in wsteth which trades at 1.17 eth per wsteth. To address this, there is an `Exchange Rate` in the Cork Pool. The Exchange Rate determines how many Reference Assets you need to deposit to receive a Collateral Asset. The higher the Exchange Rate, the fewer Reference Assets need to be deposited.

For example in the above wsteth example it would compute as follows:

$$
\text{Mint} \ 1\ eth = 1\ Cork\ Principal\ Token + 1\ Cork\ Swap\ Token
$$

$$
\text{Exercise Swap} \ 1\ Cork\ Swap \ Token + 0.854\ wsteth = 1\ eth
$$

In the case the Collateral Asset is accruing yield in excess of the Reference Asset, the Exchange Rate is continuously decreased in accordance with the differential yield generated by the Collateral Asset and the Reference Asset. This is important to protect Cork Principal Token holders such that their yield continues to accrue in the Cork Pool, without updating the Exchange Rate accrued yield could be arbitraged out by exercising swaps. For example if the Collateral Asset is accruing 10% APY, the Exchange Rate should decrease by 10% per year (which means you need to deposit a larger quantity of Reference Assets to exercise the swap). However, if the Reference Asset accrues 6% APY the differential is only 4%, which means over the course of a year the Exchange Rate would only decline 4%.

## Exercise Swap Mechanism

A user can exercise their Cork Swap Token by depositing 1 Reference Asset + 1 Cork Swap Token to receive 1 Collateral Asset from the Cork Pool (minus an exercise fee). This means holding a Cork Swap Token enables you to redeem the Collateral Asset at a 1:1 relationship with the Reference Asset.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F5CkiZ6VqhWFk2V8xBeZZ%2Fimage.png?alt=media&amp;token=b6c0dfa2-2314-44ff-9b8a-73085435ddea" alt=""><figcaption></figcaption></figure>

In the presence of a Cork Swap Token the Reference Asset inherits the liquidity of the Collateral Asset, since they can always be swapped 1:1. This has huge implications for the risk profile of the Reference Asset as collateral (eg in lending markets) since the Collateral Asset often has orders of magnitude more liquidity than the Reference Asset. Let's take a bridge as an example. Agglayer's Vault Bridge rehypothecates bridge collateral by depositing it into Morpho Vaults, which use this collateral to back loans. Due to the typically high utilization rates of these Morpho Vaults (often \~90%), the amount of collateral immediately available for withdrawals is limited. For example, at 90% utilization, only 10% of the bridge collateral can be simultaneously withdrawn. This means that if a large number of users want to bridge back to Ethereum mainnet at any given time, there will not be enough liquidity available to service those redemptions from the vault. The Cork Pool enables vaults to offer early redemptions without compromising capital efficiency or user experience. Liquidity providers deposit liquid assets (e.g., stETH, sUSDS) into a Cork Pool, allowing bridge operators to purchase fully-collateralized Cork Swap Tokens that guarantee liquidity to meet user redemptions in any market conditions. In return, LPs earn native yield plus a risk premium—while bridge managers benefit from a redemption buffer that maintains user confidence in black swan scenarios.

Cork Swap Tokens change the liquidity risk profile for larger investors since with the available liquidity on many Reference Assets it is difficult to immediately liquidate big positions. For such users, the immediate liquidity guarantee from Cork Swap Tokens is another use case and form of utility for the token beyond the hedge. This is particularly useful to manage duration mismatch risks, which is a common challenge for vaults.

If the Reference Asset loses value relative to the Collateral Asset, holders of the Cork Swap Token can profit by exercising and receiving the Collateral Asset from the Cork Pool. The value of the Cork Swap Token is therefore related to the CA:REF relative price and implied risk of the Reference Asset. The Cork Swap Token becomes a market to price the risk of the Reference Asset.

For example in an LRT-ETH pair, if the Reference Asset falls to 0.8 ETH, the Cork Swap Token will then be worth at least 0.2 ETH. If an investor bought the Cork Swap Token for 0.01 ETH, the position is now worth 0.2 ETH — a 20x return on the cST. This illustrates the leveraged exposure inherent in the Cork Swap Token: limited downside (the premium paid) with asymmetric upside when the Reference Asset loses value.

#### **Repurchase Mechanism**

When the Cork Pool receives Reference Asset + Cork Swap Token tokens during periods of swaps being exercised, these assets can be repurchased to facilitate potential arbitrage. The Reference Asset Repurchase Mechanism allows you to repurchase the Reference Asset + Cork Swap Token with the original amount of Collateral Asset (minus a fee that linearly decreases with time to expiry). The exchange is as follows:

$$
cST + REF = CA + \text{fee}
$$

There are two scenarios where one would do this. If the price of Cork Principal Token < Reference Asset, then both the Reference Asset and Cork Swap Token can be sold to Collateral Asset for a profit. Alternative if the price of Cork Swap Token + Reference Asset > Collateral Asset, then these are sold to Collateral Asset for a profit. Arbitrage bots will automatically execute such trades to keep the Cork Swap Token and Cork Principal Token in line with the Reference Asset price.

**How to treat the Reference Asset in the Cork Pool**

When swaps are exercised, some Collateral Asset is replaced by Cork Swap Token + Reference Asset. In a scenario where the Reference Asset returns to its usual liquidity profile, the Cork Pool will be restored to holding just Collateral Asset through the Repurchase Mechanism. If that does not happen, the Reference Asset is held in the Cork Pool to be redeemed at expiry by Cork Principal Token holders.

Take a scenario where the Reference Asset temporarily loses value relative to the Collateral Asset — the Repurchase mechanism can generate profit. For example, in an LRT:ETH pair trading 1:1, with cST priced at 0.02 ETH: if the LRT falls to 0.9 ETH, the cST might trade at 0.13 ETH as the market prices in further risk. At this point, spending 1 ETH to repurchase REF + cST from the pool (even with a fee) is profitable because the combined value of REF + cST exceeds 1 ETH. Any time there is a temporary price deviation and recovery, there is likely a profit to be made through the Repurchase mechanism.


# Swap Token

Cork Swap Token (cST) — the tokenized risk instrument for pricing, hedging, and trading onchain risk

{% hint style="info" %}
**TL;DR:** The Cork Swap Token (cST) is a tokenized risk instruments that allows market participants to price, hedge, and trade the risk associated with a Reference Asset.
{% endhint %}

### Introduction

Many assets in DeFi carry specific forms of risk — duration, illiquidity, credit, and price deviation risks. These risks affect numerous market participants and asset types, including institutional users, vaults, and asset issuers. The Cork Swap Token is a DeFi primitive that allows you to price, hedge, and trade such risks.

***

### How Swap Tokens Work

On Cork, every market pairs a **Reference Asset** (e.g. a RWA credit fund) with a Collateral Asset (eg sUSDS).

A **Swap Token** is a tokenized derivative that grants the holder the right, at any time before a set expiry date, to immediately exchange a specified **Reference Asset** plus the **Swap Token** for a **Collateral Asset** at pre-defined terms.

$$
Swap\ Token + Reference\ Asset = Collateral\ Asset
$$

***

### A Solution for Duration Risk

A major use case for Swap Tokens is to act as a liquidity facility to hedge against duration risk. Certain assets, such as RWAs with long redemption windows (eg 40+ days), are difficult to leverage in DeFi due to the lack of secondary liquidity whilst the asset carries significant duration risk. To make such asset composable with lending markets, vaults etc. which may require more immediate liquidity, a Cork Pool can be configured with the RWA as a Reference Asset and a liquid Collateral Asset. This means, that the previously illiquid RWA, can be instantly swapped to a liquid collateral through the use of the Swap Token. As a result, it can become composable with the rest of DeFi, solving the Duration Risk challenge of the RWA.

***

### Applications of Swap Tokens

Swap Tokens can provide coverage for a wide range of risks and use cases including:

* **Looping**: Swap Tokens can be used in looping trades to shield against liquidation events and provide instant liquidity in particular to illiquid assets (eg Vault Tokens, RWAs)
* **Duration Risk:** In addition to RWAs, other market participants including Vaults and Bridges which may face significant duration mismatches in their business, can leverage Cork to gain a more capital efficient liquidity buffer to support smooth functioning in volatile market conditions.
* **Price deviation risk:** Temporary or permanent loss of value relative to the Collateral Asset can be hedged with Cork Swap Tokens.
* **Credit risk**: Instruments with credit risk, such as credit funds or certain stablecoins, can be hedged.


# Principal Token

Cork Principal Token (cPT) — underwriting exposure with yield from premiums and Collateral Asset accrual

{% hint style="info" %}
**TL;DR:** Liquidity providers who seek to underwrite risk can mint Principal Tokens + Swap Tokens, to earn a fixed premium from the sale of the Swap Tokens. The Principal Token represents the proportional ownership of principal in the Cork Pool.
{% endhint %}

### Introduction

In Cork, Swap Token holders pay a premium to Principal Token holders in exchange for them underwriting the risk which is hedged with the Swap Tokens. Principal Tokens represent the primary underwriting token and is the main "yield strategy" for liquidity providers in Cork.

***

### How Principal Tokens Work

In a Cork Pool, a Collateral Asset can be deposited to mint two tokens: Swap Token + Principal Token. The Principal Token represents the fractional ownership of the principal in the Cork Pool. At expiry, the Principal Token holder can claim the assets (including yield generated by the Collateral Asset). If Swap Tokens have not been exercised, the Principal Token holder receives back the original Collateral Asset. If Swap Tokens have been exercised, they could receive a combination of Collateral Asset and Reference Asset (which may be impaired or face duration risk). As such, the Principal Token holder is effectively exposed to the performance of the Collateral Asset and Reference Asset, if either is impaired through the expiry, the underwriter may face a loss.<br>

Underwriters furthermore can earn a fixed yield by selling the Swap Token in exchange for a premium. Effectively, the premium is the price which Swap Token holders are paying for the liquidity and hedging facility provided to them my the underwriter. In other words, the price of the risk.<br>

At any time before expiry, combining Principal Token + Swap Token can effectively reconstitute the Collateral Asset at a 1:1 ratio, thus unwinding the exposure.

$$
Principal\ Token + Swap\ Token = Collateral\ Asset
$$

***

### Yield Sources

Principal Tokens can earn a yield through a variety of sources:

* **Collateral Asset yield:** The native yield of the Collateral Asset (such as sUSDS or wstETH) accrues to the Principal Token holder.
* **Premium**: The fixed yield earned by selling minted Swap Tokens.
* **Fees**: In some Cork Pools, the fee revenue from the Exercise Swap fee and Repurchase Fee may flow to Principal Token holders
* **Incentives**: Token incentives from partners and Cork generally accrue to Principal Token holders.
* **Rehypothecation**: The Principal Token represents quality collateral in many cases, which can compose with other DeFi building blocks such as lending markets to perform looping trades to amplify yield.


# Reference Asset

{% hint style="info" %}
**TL;DR:** The Reference Asset (REF) is the asset whose risk is being priced and hedged in a Cork Pool. It is the asset that Cork Swap Token holders deposit alongside their cST when exercising the Swap operation.
{% endhint %}

### Introduction

Every Cork Pool pairs a [**Collateral Asset**](/core-concepts/collateral-asset) with a **Reference Asset**. The Reference Asset is the asset whose liquidity, duration, or credit risk a market participant wants to manage. It could be a vault token, a liquid staking token, a stablecoin, or a tokenized real-world asset.

The Reference Asset is not deposited to create positions — that role belongs to the Collateral Asset. Instead, the Reference Asset enters the pool only when a Cork Swap Token is exercised.

***

### How It Works

Cork Pools need to identify which asset's risk is being priced and hedged. The Reference Asset fills this role — it is the target of the Swap mechanism.

$$
Cork\ Swap\ Token + Reference\ Asset \rightarrow Collateral\ Asset
$$

When a cST holder exercises via the Swap operation, they deposit the Reference Asset and transfer their cST into the Cork Pool. In return, they receive the Collateral Asset (minus an exercise fee). The cST is held by the pool and may be returned to arbitrageurs through the Repurchase mechanism. The Reference Asset remains in the pool until expiry, when it is distributed proportionally to Cork Principal Token holders alongside any remaining Collateral Asset.

If no swaps are exercised, the pool holds only Collateral Asset at expiry.

***

### Key Properties

* **Not deposited on pool creation** — The Collateral Asset funds the pool. The Reference Asset enters only through exercised swaps.
* **Defines the risk being priced** — The cST price reflects the market's assessment of the Reference Asset's risk relative to the Collateral Asset. If the Reference Asset is perceived as risky, cST becomes more valuable.
* **Exchange Rate adjusted** — A rate oracle and constraint parameters (min, max, rate-of-change limits) govern the exchange rate between the Reference Asset and Collateral Asset. For yield-bearing pairs, this rate adjusts to account for yield differentials, preventing arbitrage at the expense of cPT holders.
* **Recoverable post-exercise** — Once Reference Asset enters the pool through exercised swaps, it can be recovered before expiry through the Repurchase mechanism, or it remains for cPT holders to redeem at expiry via Withdraw.

***

### Types of Reference Assets

Cork Pools can be configured for a wide range of Reference Assets:

**Vault Tokens** — ERC-4626 vault shares, bridge vault tokens, or yield aggregator tokens. These often have limited redemption liquidity or high utilization rates, making instant exits difficult. A Cork Pool provides guaranteed liquidity through the Collateral Asset.

**Liquid Staking & Restaking Tokens** — Tokens like wstETH, ezETH, or other LST/LRT derivatives that track an underlying staked asset. While generally correlated to the base asset, they can deviate during periods of market stress or slashing events.

**Stablecoins** — Fiat-pegged tokens (USDC, USDT, DAI) or algorithmic stablecoins where price deviation risk exists. Cork Pools allow holders to hedge against temporary or permanent loss of value relative to the peg.

**Real-World Assets (RWAs)** — Tokenized bonds, credit funds, or other traditional financial instruments brought onchain. These often carry duration risk (long redemption windows of 40+ days), making them difficult to use as collateral in DeFi without a liquidity facility like Cork.

***

### Relationship to Other Components

* **CorkPoolManager** — Tracks Reference Asset balances per pool. The Reference Asset enters through the Swap operation and exits through Repurchase or Withdraw.
* **Cork Swap Token (cST)** — The cST enables exchange of REF for CA. Without the Reference Asset, the cST has no exercise target.
* **Cork Principal Token (cPT)** — At expiry, cPT holders receive their proportional share of both the remaining Collateral Asset and any Reference Asset in the pool.
* **Exchange Rate** — Determines how many Reference Asset units correspond to each cST when exercising. The rate oracle provides fundamental pricing, while constraint parameters protect against manipulation.

***

### Example

Consider a Cork Pool with **sUSDS** as the Collateral Asset and a **tokenized credit fund** (RWA) as the Reference Asset. The credit fund has a 45-day redemption window.

1. A vault manager holds 1,000 units of the credit fund but needs the ability to exit instantly if required by depositors.
2. They purchase **1,000 cST** from the market, paying a premium to a liquidity provider.
3. If the credit fund enters a liquidity crisis (e.g., redemption queue grows, secondary market dries up), the vault manager exercises via the Swap operation: they deposit credit fund tokens alongside their 1,000 cST (the Reference Asset amount determined by the current exchange rate) and receive the equivalent value in sUSDS immediately, minus the exercise fee.
4. The credit fund tokens now sit in the Cork Pool. Arbitrageurs may Repurchase them if secondary market conditions improve. Otherwise, they are distributed to cPT holders at expiry via Withdraw.

The Reference Asset (credit fund token) is the risk being managed. The Cork Pool transforms an illiquid, duration-locked asset into something with guaranteed instant liquidity.


# Collateral Asset

{% hint style="info" %}
**TL;DR:** The Collateral Asset (CA) is the liquid, high-quality asset deposited into a Cork Pool to back all positions. It is the asset that Cork Swap Token holders receive when they exercise, and it forms the principal backing that Cork Principal Token holders have a claim on.
{% endhint %}

### Introduction

Every Cork Pool is defined by a pair of assets: a **Collateral Asset** and a [**Reference Asset**](/core-concepts/reference-asset). The Collateral Asset serves as the foundation of the pool — it is the asset deposited by liquidity providers and locked in the CorkPoolManager to collateralize positions.

The Collateral Asset is typically a yield-bearing asset such as sUSDS, wstETH, or sDAI. By choosing a high-quality, liquid Collateral Asset, Cork Pools ensure that swaps can be exercised against deep, reliable liquidity.

***

### How It Works

Cork Pools require a high-quality, liquid asset to guarantee that the Swap operation can always be exercised. The Collateral Asset fills this role.

When a liquidity provider deposits the Collateral Asset into a Cork Pool, the CorkPoolManager locks it and mints two tokens in return:

$$
Collateral\ Asset \rightarrow Cork\ Principal\ Token + Cork\ Swap\ Token
$$

The locked Collateral Asset backs both instruments. The [Cork Swap Token](/core-concepts/swap-token) (cST) gives its holder the right to exchange Reference Asset + cST for the Collateral Asset before expiry. The [Cork Principal Token](/core-concepts/principal-token) (cPT) represents proportional ownership of whatever remains in the pool at expiry — which may include both Collateral Asset and Reference Asset if swaps were exercised.

***

### Key Properties

* **Locked on Deposit** — When the Collateral Asset is deposited, it is locked in the CorkPoolManager and cannot be withdrawn until the position is unwound (via UnwindDeposit) or the pool expires (via Withdraw).
* **Backs the Swap guarantee** — The Swap operation (REF + cST → CA) draws directly from the locked Collateral Asset, minus an exercise fee.
* **Yield accrual** — If the Collateral Asset is yield-bearing (e.g., sUSDS, wstETH), that yield accrues within the pool and benefits cPT holders. The exchange rate in the pool adjusts to prevent this yield from being arbitraged through swaps.
* **Reconstitution** — Before expiry, cPT + cST can always be combined to recover the original Collateral Asset deposit, regardless of market conditions.

***

### Relationship to Other Components

The Collateral Asset connects to every major component of a Cork Pool:

* **CorkPoolManager** — Holds and manages all locked Collateral Asset balances. The Deposit operation accepts CA, and the CorkPoolManager distributes it on Repurchase or Withdraw.
* **Cork Swap Token (cST)** — Exercising a cST via the Swap operation unlocks Collateral Asset from the pool. The amount is determined by the cST quantity, adjusted by the exchange rate and exercise fee.
* **Cork Principal Token (cPT)** — At expiry, cPT holders use the Withdraw operation to redeem their proportional share of remaining Collateral Asset (and any Reference Asset that entered the pool through exercised swaps).
* **Exchange Rate** — Governed by a rate oracle and constraint parameters (min, max, rate-of-change limits), the exchange rate ensures yield differentials between the Collateral Asset and Reference Asset are accounted for, keeping the pool fair to cPT holders.

***

### Example

Consider a Cork Pool with **sUSDS** as the Collateral Asset and a **USDC Vault Token** as the Reference Asset, with a 1:1 exchange rate:

1. A liquidity provider deposits **100 sUSDS** into the Cork Pool.
2. The CorkPoolManager locks the 100 sUSDS and mints **100 cPT + 100 cST** (returned to the depositor).
3. The LP sells the 100 cST for a premium — say **2 sUSDS** — to a hedger who wants coverage on the USDC Vault Token.
4. If the hedger exercises 50 cST via the Swap operation, they deposit **50 USDC Vault Tokens + 50 cST** and receive approximately **50 sUSDS** from the pool (minus the exercise fee). The exact Reference Asset amount depends on the current exchange rate.
5. At expiry, the cPT holder uses Withdraw to redeem their 100 cPT for a proportional share of what remains: **50 sUSDS + 50 USDC Vault Tokens**.

The Collateral Asset (sUSDS) is the anchor throughout — it backs the swap, generates yield for the LP, and is the asset hedgers receive on exercise.


# Fees

How fees work in Cork Pools — types, calculation, and configuration

Cork Pools charge fees on two operations: **Exercise** and **Repurchase**. By default, fees flow to the Cork fee treasury. Governance can configure specific markets to redirect fees (partially or fully) to Cork Principal Token holders to adjust underwriting economics.

***

## Fee Types

| Fee            | Applied To                               | When                                                                   |
| -------------- | ---------------------------------------- | ---------------------------------------------------------------------- |
| Exercise Fee   | Exercise (swap / exercise)               | When exchanging Reference Asset + Cork Swap Token for Collateral Asset |
| Repurchase Fee | Repurchase (unwindSwap / unwindExercise) | When exchanging Collateral Asset for Reference Asset + Cork Swap Token |

Fees are **not** charged on Deposit, Unwind Deposit, Withdraw, or Redeem operations.

***

## How Fees Are Calculated

Fees use a **custom encoding** where `1e18 = 1%` (one percentage point). This differs from standard 18-decimal fixed-point where `1e18` would represent 100%. The fee is applied to the Collateral Asset amount involved in the operation:

```
feeAmount = amount × feePercentage / 100e18
```

**Example:** If the Exercise fee is `1e18` (1%) and you exercise for 100 Collateral Asset:

```
feeAmount = 100 × 1e18 / 100e18 = 1 Collateral Asset
```

You receive 99 Collateral Asset after the fee.

{% hint style="info" %}
Fees are rounded up (ceiling) to protect the pool. The actual fee may be fractionally higher than the formula suggests for non-round amounts.
{% endhint %}

***

## Fee Limits

The maximum allowed fee for either type is `5e18` (**5%**). Fees are configured individually for each Cork Pool at creation and can be updated by governance (DefaultCorkController) within this maximum.

***

## Querying Fees

Read the current fee for any pool on CorkPoolManager. The `MarketId` type is a `bytes32` hash that uniquely identifies a pool — see [MarketId Computation](/developers/contract-reference/cork-pool-manager#marketid-computation) for details.

```solidity
function swapFee(MarketId poolId) external view returns (uint256 fees)
function unwindSwapFee(MarketId poolId) external view returns (uint256 fees)
```

The returned value uses Cork's fee encoding (`1e18 = 1%`).

{% hint style="info" %}
The API returns fees as decimal fractions (e.g., `0.01` = 1%). On-chain, the same 1% fee is represented as `1e18` (1000000000000000000). See [API Reference](/developers/api-reference) for details.
{% endhint %}

***

## Fee Configuration

Fees are set per pool at creation via the `PoolCreationParams` struct and can be updated by governance:

```solidity
function updateSwapFeePercentage(MarketId id, uint256 newSwapFeePercentage) external
function updateUnwindSwapFeePercentage(MarketId id, uint256 newUnwindSwapFeePercentage) external
```

See [Admin & Governance](/developers/contract-reference/admin-and-governance) for the full governance interface.


# Target Assets & Use Cases

Key use cases for Cork Pools — vault liquidity, RWA looping, lending integration, and asset hedging

The primary use for Cork Swap Tokens would be to target Reference Assets offering high yields with some level of duration, illiquidity or credit risk, such as vaults, RWAs and yield bearing stablecoins. Cork Swap Tokens can offer investors the ability to earn yield from such assets whilst hedging associated risks. Furthermore, illiquid reference assets, such as vault tokens or RWAs, can through the coupling with a Cork Swap Token, become deeply liquid and as such more suitable to be used as collateral in DeFi. A few of the key use cases for Cork Phoenix include:

**Onchain Vaults**: Vaults often have high utilization rates (80%–90%), leaving limited liquidity available for instant withdrawals. For example, at 90% utilization, only 10% of collateral is immediately withdrawable, causing an asset-liability mismatch. Often vaults can earn a higher yield by committing their full set of capital towards strategies with some level of duration risk or illiquidity risk, including L2s with 1+ week withdraw delays. Under high redemption pressure, users may face liquidity shortages and delayed withdrawals. Cork’s vault liquidity solution addresses this by providing programmable, on-demand liquidity via Cork Swap Tokens, creating instant liquidity buffers that enable immediate withdrawals, regardless of the vault’s utilization rate.

**RWA Looping:** A common issue when trying to integrate RWAs into DeFi is their duration. For example many credit funds have quarterly redemption windows with multi-week redemption delays. Meanwhile, these tokens have limited secondary liquidity. This complicates the ability to integrate such assets into lending markets to perform looping trades, as liquidators are unable to take on such duration risk. By creating a Cork Pool with the RWA as a Reference Asset, it can achieve immediate deep liquidity to fully offboard duration risk to Cork underwriters. This opens up long-duration RWAs to be used as high quality collateral for looping strategies.

**Lending markets**: Users can bundle their Reference Asset with a Cork Swap Token and lever it up on lending markets. If the loan that is taken is the same as the Collateral Asset, during the duration of the Cork Swap Token, there is no liquidation risk and a very high Loan to Value (LTV) ratio could be achieved which could allow for very high leveraged farming opportunities.

**Risk free rate**: Fixed rate protocols, such as Pendle, offer investors the onchain equivalent of a zero-coupon bond that offers a fixed rate of return during a duration of time. The primary risk for the “bond holder” is that the asset you receive back will have lost value relative to its expected peg. With a Cork Swap Token, you can hedge this risk. Essentially, the fixed rate minus the price of the Cork Swap Token becomes the “risk free rate of return”. The zero-coupon bond, such as a Pendle PT, can be coupled with a Cork Swap Token with the same expiry, to achieve such an instrument.

**Asset hedging:** Investors with exposure to assets like LRTs can hedge their price risk, thereby achieving a lower risk profile. Cork Swap Tokens give investors who allocate to yield-bearing Reference Assets the choice of which level of risk and return they wish to take on. A position can be fully hedged, partially hedged, or unhedged, depending on the appetite for risk, volatility, and yield an investor wishes to take on. Pockets of capital that would like to allocate to yield opportunities such as Ethena’s USDe or LRTs, but were unable to due to perceived risks, could be unlocked with Cork Swap Tokens.

**New yield source**: Cork Principal Token represents a new form of yield generation opportunity in DeFi, which can be integrated into other dapps such as lending markets. Cork Principal Tokens can be used as collateral to further increase yield generation for underwriters.


# Whitelist Functionality

How whitelist access control works in Cork Pools

Cork Pools can optionally restrict access through a whitelist. When enabled, only whitelisted addresses can interact with that market.

***

## How It Works

Each Cork Pool can be configured with whitelist enforcement at creation. When enabled:

* **All operations are restricted** — only whitelisted addresses can interact with the market (Deposit, Exercise, Withdraw, Redeem, Unwind)
* An address is considered whitelisted if it is on the **global whitelist** OR the **market-specific whitelist**

{% hint style="info" %}
If a market's whitelist is disabled (or was never enabled), all addresses can interact with it. Public markets cannot later be whitelisted — the whitelist can only be disabled, not enabled after creation.
{% endhint %}

***

## Why Whitelisting Exists

Cork introduced whitelisting for two reasons:

1. **Security** — Restricting deposits to known addresses reduces the attack surface on whitelisted markets
2. **Institutional requirements** — Certain institutional use cases require permissioned access to comply with regulatory or operational requirements

***

## Checking Whitelist Status

### On-Chain

Query the WhitelistManager (`0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE`):

```solidity
// Combined check — returns true if whitelist is disabled OR address is whitelisted
function isWhitelisted(MarketId poolId, address account) external view returns (bool)

// Individual checks
function isMarketWhitelistEnabled(MarketId poolId) external view returns (bool)
function isGlobalWhitelisted(address account) external view returns (bool)
function isMarketWhitelisted(MarketId poolId, address account) external view returns (bool)
```

Use `isWhitelisted` for pre-flight checks before deposits. It handles all cases: if the whitelist is disabled, it returns `true` for any address.

### Via API

```
GET /v1/pools/whitelisted-addresses?chainId=1&walletAddress=0x...
```

Returns whitelist status per pool. See [API Reference](/developers/api-reference) for details.

***

## Getting Whitelisted

If a market has whitelisting enabled and you need access, contact the Cork team to be onboarded. A governance multisig manages the whitelist through the DefaultCorkController.


# Exercise Swaps

How to Swap reference assets for collateral assets using Cork Swap Tokens

Cork [**Swap Tokens**](/core-concepts/swap-token) provide protection against credit and duration risks.

Swap [**reference asset**](/core-concepts/reference-asset) into [**collateral asset**](/core-concepts/collateral-asset), by exercising your Cork [**Swap Token**](/core-concepts/swap-token) (cST) against a [**Cork Pool**](/core-concepts/cork-pool)**.**

This **"Swap /** **Exercise" operation** on Cork:

* Exercises an amount of your Cork [**Swap Token**](/core-concepts/swap-token) (i.e. reduces the token's circulating supply)
* Releases an equivalent amount of [**Collateral Asset**](/core-concepts/collateral-asset) from one of many [**Cork Pools**](/core-concepts/cork-pool)
  * This amount is 1:1 as the Cork [**Swap Token**](/core-concepts/swap-token) exercised, minus a nominal swap fee.
* Locks up "some fair amount" of your [**Reference Asset**](/core-concepts/reference-asset) in exchange.
  * This amount is determined by the **Exchange Rate**, which is a dynamic rate based on the current relative valuation between the [**Reference Asset**](/core-concepts/reference-asset) and [**Collateral Asset**](/core-concepts/collateral-asset)**.**

***

## Exchange Rate

The **Exchange Rate** is a dynamic rate that applies to each [**Cork Pool**](/core-concepts/cork-pool)**,** based on the current relative valuation between its [**Reference Asset**](/core-concepts/reference-asset) and [**Collateral Asset**](/core-concepts/collateral-asset)**.** This dynamic **Exchange Rate** is driven by a **Rate Oracle**, that ensures its liveliness.

* If either asset is backed by underlying assets, the **Rate Oracle** is configured to reference the value of the underlying assets as reported by each asset’s fundamental oracle, which is typically operated by the asset issuer.
* Price Feeds (market-based) operated by Chainlink Oracles, are then applied to determine the prevailing relative valuation between the [**Reference Asset**](/core-concepts/reference-asset) and [**Collateral Asset**](/core-concepts/collateral-asset) to obtain the incoming **Exchange Rate**.
* As this **Exchange Rate** can vary greatly, depending on what’s reported by 3rd-party oracles operating outside of Cork’s control, an upper and lower limit is applied by the Cork Protocol to ensure that the **Exchange Rate** is range-bound or constrained.
* The upper limit (i.e. ceiling) is referred to as the **Max Rate**, while the lower limit (i.e. floor) is referred to as the **Min Rate**.

Learn more about rate limits [here](/core-concepts/cork-pool#exchange-rate).

***

## How Swap Amounts are specified

When exercising your Cork Swap Token (cST), you may choose to specify either the:

* amount of [**Reference Asset**](/core-concepts/reference-asset) to swap/spend, or the
* amount of [**Swap Token**](/core-concepts/swap-token) to exercise/spend, or the
* net amount of [**Collateral Asset**](/core-concepts/collateral-asset) to receive (after fees).

Either way, you will need to account for the **Variation Margin**, which is caused by the difference between the last observed **Exchange Rate**, and the final **Exchange Rate** during settlement (i.e. at the transaction confirmation block height).

Continue reading below to learn more, or jump straight to the individual guides (sub-pages) tailored to each scenario.

***

## Variation Margin

The **Exchange Rate** of each [**Cork Pool**](/core-concepts/cork-pool) is dynamic and driven by a **Rate Oracle.**

* If the [**Reference Asset**](/core-concepts/reference-asset) has lost its relative value against the [**Collateral Asset**](/core-concepts/collateral-asset), the **Exchange Rate** decreases/falls.
  * As a result, exercising each [**Swap Token**](/core-concepts/swap-token)—including those operations pending in the mempool—would consume or **spend a greater amount** of the [**Reference Asset**](/core-concepts/reference-asset) per token exercised.
  * Conversely, due to the inverse relationship, swapping each [**Reference Asset**](/core-concepts/reference-asset)—including those operations pending in the mempool—would consume or spend a smaller amount of the [**Swap Token**](/core-concepts/swap-token), per asset exercised.
* If the [**Reference Asset**](/core-concepts/reference-asset) has improved in its relative value against the [**Collateral Asset**](/core-concepts/collateral-asset), the Exchange Rate increases/rises.
  * As a result, swapping each [**Reference Asset**](/core-concepts/reference-asset) —including those operations pending in the mempool—would consume or **spend a greater amount** of the Cork [**Swap Token**](/core-concepts/swap-token), per asset swapped.
  * Conversely, due to the inverse relationship, exercising each [**Swap Token**](/core-concepts/swap-token)—including those operations pending in the mempool—would consume or spend a smaller amount of the [**Reference Asset**](/core-concepts/reference-asset) per token exercised.

Changes in the **Exchange Rate** between the time an operation is submitted (or at the last observed block height) and at the time it is settled (i.e., the transaction confirmation block height) can lead to **differences in the final settlement amounts**.

We refer to the difference between the **preview amount** and the actual **settlement amount** as the [**Variation Margin**](https://www.investopedia.com/terms/v/variationmargin.asp). Because this margin is determined by the prevailing Exchange Rate at each transaction's execution block height, it is inherently influenced by each transaction's priority-gas fees and prevailing network conditions.

***

## How this matters

As there is a chance that a **greater spending amount** is required for each swap / exercise operation to succeed, users must provision an additional amount, called the **Spare Allowance**, within each submitted transaction.

{% hint style="info" %}
This **Spare Allowance Requirement** applies when submitting either via:

* a multisig wallet like safe.global
* an EoA wallet or MPC wallet
* a smart contract (including vaults and wrappers) while specifying a **fixed** amount.
  {% endhint %}

<details>

<summary>The <strong>Spare Allowance</strong> amount recommended depends on each use-case:</summary>

* If you are trying to ensure that your swap [**Reference Asset**](/core-concepts/reference-asset) operation is confirmed *within the near future*,
  * Take the **Current-Exchange-Rate** minus the **Current-Rate-Change-Balance,** and multiply this by the amount of [**Reference Asset**](/core-concepts/reference-asset)**,** to determine the total amount of [**Swap Token**](/core-concepts/swap-token) that must be provisioned within each submitted transaction.
* If you are trying to ensure that your exercise [**Swap Token**](/core-concepts/swap-token) operation is confirmed *within the near future*,
  * Take the amount of [**Swap Token**](/core-concepts/swap-token)**,** and divide this by **Current-Exchange-Rate** plus the **Current-Rate-Change-Balance,** to determine the total amount of [**Swap Token**](/core-concepts/swap-token) that must be provisioned within each submitted transaction.
* If you are trying to fully hedge against a vault's position in the [**Reference Asset**](/core-concepts/reference-asset)**,**
  * Take the **Min-Exchange-Rate** and multiply this by the amount of [**Reference Asset**](/core-concepts/reference-asset)**,** to determine the gross amount of [**Swap Token**](/core-concepts/swap-token) that must be held.
  * To obtain a more precise net amount, you also have to consider the **Decaying Swap Fee** in the next section.
* If you are applying a partial hedge, meaning allowing a haircut on your vault's position in the [**Reference Asset**](/core-concepts/reference-asset)**,** and **exercising swaps automatically by operating a bot,**
  * Take the **Current-Exchange-Rate** minus the **Max-Rate-Change-Capacity,** and multiply this by the amount of [**Reference Asset**](/core-concepts/reference-asset)**,** to determine the approximate worst-case swap value of your position, denominated in [**Collateral Asset**](/core-concepts/collateral-asset).
  * To obtain a more precise amount, you also have to consider the **Decaying Swap Fee** in the next section.
* If you are applying a partial hedge, meaning allowing a haircut on your vault's position in the [**Reference Asset**](/core-concepts/reference-asset)**, but exercising swaps manually,**
  * Take the **Current-Exchange-Rate** minus the **Max-Rate-Change-Capacity,** minus **the Max-Rate-Change-Per-Day for every 24 hours of delay** (in exercising your swaps)**,** and multiply this by the amount of [**Reference Asset**](/core-concepts/reference-asset)**,** to determine the approximate worst-case swap value of your position, denominated in [**Collateral Asset**](/core-concepts/collateral-asset).
  * To obtain a more precise amount, you also have to consider the **Decaying Swap Fee** in the next section.

</details>


# Provide Liquidity

How to earn yield on Cork Protocol by underwriting risk as a liquidity provider

Liquidity providers deposit Collateral Asset into a Cork Pool to mint [Cork Principal Tokens](/core-concepts/principal-token) and [Cork Swap Tokens](/core-concepts/swap-token). By selling the Cork Swap Tokens at a premium, the LP earns yield while taking on the underwriting risk represented by the Cork Principal Token.

## What You'll Need

* **Collateral Asset** (e.g., sUSDe, sUSDS) in your wallet
* A wallet that supports the Cork dApp or direct contract interaction (SAFE Wallet recommended for multisig users)

## Operations

| Action                      | What It Does                                                              | When To Use                   |
| --------------------------- | ------------------------------------------------------------------------- | ----------------------------- |
| **Mint** (Deposit)          | Deposit Collateral Asset → receive Cork Principal Token + Cork Swap Token | Enter a new position          |
| **Unwind** (Unwind Deposit) | Return Cork Principal Token + Cork Swap Token → receive Collateral Asset  | Exit a position before expiry |
| **Redeem** (Withdraw)       | Return Cork Principal Token → receive Collateral Asset + Reference Asset  | Claim assets after expiry     |

## Guides

* [Mint Tokens](/user-guides/provide-liquidity/mint-tokens) — Overview of minting and the LP position lifecycle
* [Mint Tokens (without dApp)](/user-guides/provide-liquidity/mint-tokens-without-dapp) — Step-by-step guide using SAFE Wallet transaction builder
* [Mint Tokens (without dApp or Batch-Capable Wallet)](/user-guides/provide-liquidity/mint-tokens-without-dapp-or-batch-capable-wallet) — Guide for standard wallets via Blockscout


# Mint Tokens

How to Mint Swap Token and Principal Token to earn a premium or yield

Provide cover against credit and duration risks, by depositing [**collateral assets**](/core-concepts/collateral-asset) into a [**Cork Pool**](/core-concepts/cork-pool) to mint shares of Cork [**Principal Token**](/core-concepts/principal-token) (cPT) and Cork [**Swap Token**](/core-concepts/swap-token) (cST).

This **"Mint" operation** on Cork:

* deposits [**Collateral Asset**](/core-concepts/collateral-asset) into one of many [**Cork Pools**](/core-concepts/cork-pool)
* mints share tokens (i.e. increases circulating supply of cPT & cST tokens of that Cork Pool)

***

## How it works

At maturity, [**Principal Tokens**](/core-concepts/principal-token) can be redeemed for underlying assets — typically the [**Collateral Asset**](/core-concepts/collateral-asset), or alternatively some [**Reference Asset**](/core-concepts/reference-asset), **only if** [**Cork Swap Token**](/core-concepts/swap-token) holders have exercised their cover (and these are not repurchased *by arbitragers before the Cork* [*Swap Token*](/core-concepts/swap-token)*'s expiry date).*

This mechanism is how [**Principal Token**](/core-concepts/principal-token) holders underwrite duration and credit risks.

{% hint style="info" %}
Cork [**Principal Tokens**](/core-concepts/principal-token) are expected to start at a **discounted price** the moment they are minted, and gradually move toward the value of **1** [**Collateral Asset**](/core-concepts/collateral-asset) as they approach maturity — *as long as Cork* [*Swap Tokens*](/core-concepts/swap-token) *are not exercised (or exercised tokens are fully repurchased by arbitragers before the Cork* [*Swap Token*](/core-concepts/swap-token)*'s expiry date).*
{% endhint %}

***

## How to obtain Cork Tokens

You may choose to **mint Cork** [**Principal Tokens**](/core-concepts/principal-token) **&** [**Swap Tokens**](/core-concepts/swap-token)**,** or you may choose to **purchase them from a resale market** (such as Airswap OTC):

* **If minting principal tokens:**
  * You deposit and lock up one [Collateral Asset](/core-concepts/collateral-asset) for each Cork [Principal Token](/core-concepts/principal-token) to be minted. As part of this process, you receive an equivalent amount of Cork [Swap Token](/core-concepts/swap-token).
  * This lock applies until the expiry of the [Cork Pool](/core-concepts/cork-pool) (which coincides with the expiry of the Cork [Swap Token](/core-concepts/swap-token), and maturity of the Cork [Principal Token](/core-concepts/principal-token)).
    * To redeem the Cork [Principal Token](/core-concepts/principal-token) early, you would have to obtain and burn the equivalent amount of Cork [Swap Token](/core-concepts/swap-token) too, in order to unlock and withdraw collateral assets early. This is called an **"Unwind" operation**.
  * Your "yield" or premium comes from the sale of your minted Cork [Swap Tokens](/core-concepts/swap-token) on a resale market (such as Airswap).
* **If buying principal tokens:**
  * Before maturity, Cork [**Principal Tokens**](/core-concepts/principal-token) are sold at a discount (from their expected value at maturity).
  * At maturity, Cork [**Principal Tokens**](/core-concepts/principal-token) can be redeemed for an equivalent amount of [**Collateral Asset**](/core-concepts/collateral-asset) (or [**Reference Asset**](/core-concepts/reference-asset)) from the associated [**Cork Pool**](/core-concepts/cork-pool).
  * Increased demand for Cork [**Principal Tokens**](/core-concepts/principal-token) on the resale market can drive up their price, reducing the discount (on your purchase) and resulting in a lower implied fixed yield rate to maturity (YTM).
  * Increased supply of Cork [**Principal Tokens**](/core-concepts/principal-token) on the resale market can lower their price, increasing the discount (on your purchase) and resulting in a higher implied fixed yield rate to maturity (YTM).

***

## Mint Both Principal & Swap Token

To mint both Cork Principal Tokens (cPT) and Cork Swap Tokens (cST), deposit Collateral Assets into a Cork Pool via the dApp. You can then resell the Cork Swap Tokens (e.g. on Airswap OTC) to earn a premium.

***

## Buy Principal Token only

To buy Cork Principal Tokens at a discount, purchase them from a resale market (such as Airswap OTC). At maturity, redeem them for the underlying Collateral Asset to earn an implied fixed yield.


# Mint Tokens (without dApp)

How to Mint Swap Token and Principal Token using an atomic EIP-5792 capable wallet

Provide cover by depositing [**collateral assets**](/core-concepts/collateral-asset) into a [**Cork Pool**](/core-concepts/cork-pool) to mint shares of Cork [**Principal Token**](/core-concepts/principal-token) (cPT) and Cork [**Swap Token**](/core-concepts/swap-token) (cST), without using our dApp.

This **"Mint" operation** on Cork:

* deposits [**Collateral Asset**](/core-concepts/collateral-asset) into one of many [**Cork Pools**](/core-concepts/cork-pool)
* mints share tokens (i.e. increases circulating supply of cPT & cST tokens of that Cork Pool)

***

## **How to Mint Shares of a Cork Pool via an Escrowed Deposit**

{% hint style="info" %}
You will be performing a trust-minimized escrowed operation. This is enforced by our escrow smart contract (CorkAdapter) to ensure that the end-user's desired intent is fulfilled properly with the expected outcomes. A deadline also ensures that your tokens are never stuck in an inconsistent state.
{% endhint %}

**Prerequisites:**

* The Cork Pool's market id (bytes32).
  * A balance of [**Collateral Asset**](/core-concepts/collateral-asset) **(CA)** that pertains to this [**Cork Pool**](/core-concepts/cork-pool).
* An *atomic* [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet such as SAFE Wallet by safe.global (previously Gnosis SAFE) or an "AA" Account-Abstraction Wallet.
  * For your own safety, you are advised to use a wallet that supports clear signing (i.e. some form of calldata and bundle visualization) that improves opsec.
* Completed a due diligence audit of the `safeDeposit` function on `Line 126` of the escrow manager contract (CorkAdapter) at its live deployment address via either:
  * **Sourcify.dev:** <https://repo.sourcify.dev/1/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407>
  * **Blockscout:** <https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=contract_source_code>
  * **Github:** [Link](https://github.com/Cork-Technology/phoenix/blob/d8d469b0189184179f64ab6e4410b1cda8fcace4/contracts/periphery/CorkAdapter.sol#L126-L168)

***

{% hint style="info" %}
The instructions below are prepared using SAFE Wallet by SAFE Labs (safe.global), but also applies to any atomic [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet.
{% endhint %}

### Step 1: Open your Wallet's Transaction Builder

Before we begin, check that you’re using the latest version of your browser by visiting [whatismybrowser.com](https://www.whatismybrowser.com/). If it’s not up to date, please update your browser to the latest version before continuing.

Open the SAFE Wallet's Transaction Builder using this link: <https://app.safe.global/share/safe-app?appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder>

<details>

<summary>Alternatively, you may navigate to the Transaction Builder by following these steps:</summary>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FShp9kVymmmf6AUCcdvGE%2FScreenshot%202026-01-12%20at%205.07.03%E2%80%AFPM.png?alt=media&amp;token=58820d76-22f0-4f72-ac8e-0468750ce61d" alt="SAFE Wallet Connect Button"><figcaption><p>a. Press [Connect]</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F0d6ys4PvG86IeVofSnz0%2FScreenshot%202026-01-12%20at%205.07.14%E2%80%AFPM.png?alt=media&amp;token=fd1973f2-a055-4f19-a567-94ae9e6ccb1b" alt="SAFE&#x27;s Connect Wallet Modal Window"><figcaption><p>b. Select your wallet</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FTmMkctReDsxoy389ulap%2FScreenshot%202026-01-12%20at%205.07.58%E2%80%AFPM.png?alt=media&amp;token=6be9323a-886e-4a30-afd9-4b8feb3b299b" alt="SAFE Wallet Sidebar"><figcaption><p>c. Press the [☰] hamburger button (if you do not see the sidebar), and select [New transaction].</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FQUaKiJepngj7htQapdFf%2FScreenshot%202026-01-12%20at%205.08.21%E2%80%AFPM.png?alt=media&amp;token=f3148c20-0762-4abc-80be-9e596ac1c751" alt="SAFE Wallet New Transaction Modal"><figcaption><p>d. Select [Transaction Builder].</p></figcaption></figure>

</details>

***

### Step 2: Add Transaction #1 – Transfer Collateral Assets to the Escrow Contract

Add the 1st transaction to transfer collateral assets into our trust-minimized escrow manager contract (CorkAdapter):

* **Enter Address:** `eth:<ERC20 token address of Collateral Asset>`
* **To Address:** `<ERC20 token address of Collateral Asset>`
* **Contract Method Selector:** `transfer`
  * **to (escrow address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
  * **amount (of collateral):** \<wei amount of collateral asset to transfer/deposit>

<details>

<summary>How to obtain ERC20 token address of Collateral Asset</summary>

The [Collateral asset](/core-concepts/collateral-asset) (CA) address and [Reference asset](/core-concepts/reference-asset) (REF) address may be obtained by calling `CorkPoolManager.assets(poolId)` with the [Cork Pool](/core-concepts/cork-pool) id, via either:

* **Etherscan (Closed source):** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F4)
* **Blockscout (Open source):** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0x9fda5b66)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"assets(bytes32)(address collateralAsset, address referenceAsset)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

</details>

By following these instructions:

{% stepper %}
{% step %}

### Enter ERC20 Address of Collateral Asset

Input the Collateral Asset's ERC20 address & ABI as shown below.

* **Enter Address:** `eth:<ERC20 token address of Collateral Asset>`
* **Enter ABI:** If the ABI does not load automatically, copy and paste the ABI from [here](https://eth.blockscout.com/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2?tab=contract_abi).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FJ68zSvACUtpeauoh0TVW%2FScreenshot%202026-01-12%20at%204.20.36%E2%80%AFPM.png?alt=media&amp;token=d2540286-1431-42ce-922e-814424592f0f" alt=""><figcaption><p>Input ERC20 token address</p></figcaption></figure>
{% endstep %}

{% step %}

### Calculate the deposit amount in wei

To calculate the right wei-amount of collateral asset (CA), first obtain the token decimals of the collateral asset from its ERC20 contract address, then multiply your amount by 10<sup>^</sup>(erc20\_decimal\_of\_CA).

For example, 10 USDC (which has 6 decimals) is represented as![](data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==) $$10 \times 10^{6}$$ , which is `10 000 000` in wei-amount.

Use a unit converter that allows you to adjust the token decimals, such as:\
[https://converter.swiss-knife.xyz/eth](https://converter.swiss-knife.xyz/eth?wei=1000000000000000000)<br>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FGpRA5QW80pvPki3udYlI%2FScreenshot%202026-01-12%20at%204.21.03%E2%80%AFPM.png?alt=media&amp;token=3ab03497-52a0-4fc3-ac7e-5d3c2dd2634c" alt=""><figcaption><p>Input the amount under "Ether", adjust the decimals of "10^6", then press [Copy] button to its right.</p></figcaption></figure>
{% endstep %}

{% step %}

### Input Transaction #1 Details

* **To Address:** `<ERC20 token address of Collateral Asset>`
* **Contract Method Selector:** `transfer`
* **to (address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **amount (uint256):** \<wei amount of collateral asset to transfer/deposit copied from above>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FaD5hGYLmh2FHhMKDBC9e%2FScreenshot%202026-01-12%20at%204.21.43%E2%80%AFPM.png?alt=media&amp;token=04f6bc72-8fca-45e6-bb39-03514369f1f0" alt=""><figcaption><p>Input transaction details under Transaction Information</p></figcaption></figure>
{% endstep %}

{% step %}

### Append Transaction #1

Press **\[+ Add new transaction]** and verify that transaction #1 has been added to the Transactions Batch.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F5rdh4Js9nvZhPQE1OzcC%2FScreenshot%202026-01-12%20at%204.22.27%E2%80%AFPM.png?alt=media&amp;token=aceaeee6-5b6a-42b9-a56c-b3573def4a75" alt=""><figcaption><p>Press [Add new transaction]</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 3: Add Transaction #2 – Request a Deposit/Mint with escrowed assets

Add the 2nd transaction to mint cPT (Cork [Principal Token](/core-concepts/principal-token)) and cST (Cork [Swap Token](/core-concepts/swap-token)) by depositing escrowed collateral assets into a Cork Pool:

* **Enter Address:** `eth:0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`
* **Enter ABI:** Copied from [here](https://eth.blockscout.com/address/0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245?tab=contract_abi)
* **To Address:** `0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`
* **ETH value:** `0`
* **Contract Method Selector:** `multicall`
  * **bundle:** `[[comma separated values as below within double square brackets...]]`
    * `"0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407"`,
      * The `to` address is the call target, which is the escrow contract address
    * `"<calldata>"`,
      * The `calldata` as copied from the [safeDeposit Step](#input-safedeposit-parameters).
    * `"0"`,
      * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
    * `false`,
      * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To protect escrowed funds, we must also revert the transfer-to-escrow if the deposit fails.
    * `"0x0"`
      * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.

<details>

<summary><strong>Show me an example of bundle:</strong></summary>

```json
[[
"0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0", 
false, 
"0x0"
]]
```

</details>

By following these instructions:

{% stepper %}
{% step %}

### Enter Address of Bundler3 contract

{% hint style="info" %}
A Bundler contract is analogous to a Router contract, with the added guarantee that each step of the execution is explicitly defined rather than implicit.

This reduces the need to absolutely verify and place trust in esoteric code when interacting with smart contracts.

By ensuring that each step is verifiable by a mainstream enduser and his wallet, this system achieves greater end-to-end transparency and security.
{% endhint %}

Input the [Bundler3 contract address](https://docs.morpho.org/get-started/resources/addresses/#bundlers) & ABI as shown below.

* **Enter Address:** `eth:0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`
* **Enter ABI:** If the ABI does not load automatically, copy and paste the ABI from [here](https://eth.blockscout.com/address/0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245?tab=contract_abi).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FWUS8ylxdWhRDtO3Zu7Re%2FScreenshot%202026-01-20%20at%2011.44.46%E2%80%AFPM.png?alt=media&amp;token=7bba45ca-aa75-4925-a7cd-1b18577b2a32" alt=""><figcaption><p>Input Bundler3 contract address</p></figcaption></figure>
{% endstep %}

{% step %}

### Optional: Calculate the deadline in seconds since epoch

Choose a time in the future using an [epoch-converter](https://epoch-converter.swiss-knife.xyz/). We recommend setting it **at least 1 hour from now** to allow sufficient time for cosigning. Since the bundle executes atomically, time-limited ERC-20 permits are unnecessary, allowing this timestamp to be set as far in the future as desired. Use this timestamp as the `deadline` in the next step.

{% hint style="info" %}
DO NOT attempt to retry this transaction before the deadline has passed.

Retrying earlier may result in duplicate operations, unintended consequences, or loss of funds.
{% endhint %}

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FySToACQkox4dHDTfFsD2%2FScreenshot%202026-01-12%20at%204.31.26%E2%80%AFPM.png?alt=media&amp;token=76977186-8037-4989-8740-b7750038f88a" alt=""><figcaption><p>Input your desired duration from now</p></figcaption></figure>

If missing, scroll to the right of the page to see the copy button:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FJ9GfVblSqwbhknq2Pb0w%2FScreenshot%202026-01-12%20at%204.31.30%E2%80%AFPM.png?alt=media&amp;token=cab350cd-a0ea-447f-bc2c-0046fe133b9d" alt=""><figcaption><p>Press [Copy] button</p></figcaption></figure>
{% endstep %}

{% step %}

### Input SafeDeposit Parameters

Input these parameters into the "safeDeposit" form linked [here](https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=write_contract#0x41881406):

* **Contract Method:** `safeDeposit`
  * **params:**
    * **poolId** (bytes32)
      * The cork pool market id
    * **collateralAssetsIn** (uint256)
      * The wei amount of collateral assets to deposit. ~~Use \[Max]~~ or input **the same** wei amount being transferred to escrow in [Step 2](#step-2-add-transaction-1-transfer-collateral-assets-to-the-escrow-contract).
    * **receiver** (address)
      * Your wallet address. Or the address to which shares (cST & cPT) will be minted.
    * **minCptAndCstSharesOut** (uint256)
      * The amount (non-denominated in wei) of Collateral Asset in [Step 2](#step-2-add-transaction-1-transfer-collateral-assets-to-the-escrow-contract), multiplied by 10<sup>18</sup>.
      * This guarantees the minimum amount of shares (cST & cPT) to receive.
    * **deadline** (uint256)
      * The deadline by which the transaction must be completed. Use **\[Now+1h]** or copy from an [epoch-converter](https://epoch-converter.swiss-knife.xyz/).
* Press **\[Copy calldata]**.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FAuHx1KIJaYQFZkFg1Gkq%2FScreenshot%202026-01-20%20at%2010.28.39%E2%80%AFPM.png?alt=media&amp;token=830a253f-355a-4820-8090-0fd0164918e7" alt=""><figcaption><p>Input transaction details and press [Copy calldata]</p></figcaption></figure>

{% hint style="info" %}
DO NOT attempt to retry this transaction before the deadline has passed.

Retrying earlier may result in duplicate operations, unintended consequences, or loss of funds.
{% endhint %}
{% endstep %}

{% step %}

### Optional: Verify copied calldata

Copy and paste the calldata into the Calldata Decoder linked [here](https://calldata.swiss-knife.xyz/decoder?address=0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407\&calldata=0x\&chainId=1), and press **\[Decode]** to verify your inputs:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fbpn47ozkh3MmVXyxNKuH%2FScreenshot%202026-01-21%20at%202.14.07%E2%80%AFAM.png?alt=media&amp;token=100a15d7-3b33-480f-b745-64e5ccc01b9d" alt=""><figcaption><p>Verify that the values displayed are correct</p></figcaption></figure>
{% endstep %}

{% step %}

### Input Transaction #2 Details

* **To Address (**[**Bundler3**](https://docs.morpho.org/get-started/resources/addresses/#bundlers)**):** `0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`
* **ETH value:** `0`
* **Contract Method Selector:** `multicall`
* **bundle:** `[[comma separated values as below within double square brackets...]]`
  * `"0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407"`,
    * The `to` address is the call target, which is the escrow contract address
  * `"<calldata>"`,
    * The `calldata` as copied from the [safeDeposit Step](#input-safedeposit-parameters).
  * `"0"`,
    * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
  * `false`,
    * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To protect escrowed funds, we must also revert the transfer-to-escrow if the deposit fails.
  * `"0x0"`
    * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.
* **Example bundle:**

```json
[[
"0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0", 
false, 
"0x0"
]]
```

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FI6JBPB3RJ49SxAqWtcP8%2FScreenshot%202026-01-20%20at%2011.24.35%E2%80%AFPM.png?alt=media&amp;token=4f43cf6d-3e43-46a0-ad37-2ab9870a288c" alt=""><figcaption><p>Input transaction details under Transaction Information</p></figcaption></figure>
{% endstep %}

{% step %}

### Append Transaction #2

Press **\[+ Add new transaction]** and verify that transaction #2 has been added to the Transactions Batch.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F20jRr3d8MQK2PUINCNmD%2FScreenshot%202026-01-20%20at%2011.26.57%E2%80%AFPM.png?alt=media&amp;token=d6959da9-8936-4dab-b025-664851b3cca4" alt=""><figcaption><p>Press [Add new transaction]</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 4: Create, Review & Simulate Transactions Batch

Press **\[Create Batch]** and follow these instructions:

{% stepper %}
{% step %}

### Review and Confirm your Batch

Make sure that you see this **"Review and Confirm"** screen.

**Important:** Enable ***atomic batch*** if asked by your [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet. Using non-atomic batch mode can lead to lost of funds!

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fht70bY6GFAGCiU5H1P6f%2FScreenshot%202026-01-21%20at%2012.00.02%E2%80%AFAM.png?alt=media&amp;token=7c037c68-c6f6-4007-8e93-b09a52f41518" alt=""><figcaption><p>Ensure that there are 2 items (transfer &#x26; multicall) in the Atomic Batch</p></figcaption></figure>
{% endstep %}

{% step %}

### Verify each Transaction in your Batch

<details>

<summary>An example of each transaction in the batch:</summary>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FaQRwHz69JEYmdod9oYH4%2FScreenshot%202026-01-20%20at%2011.33.39%E2%80%AFPM.png?alt=media&amp;token=5b6b7424-aa0a-496f-8077-0b009526999f" alt=""><figcaption><p>Ensure that "method", "to" and "amount" are correct</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F2FwFUEl2JKbsrk42L58e%2FScreenshot%202026-01-20%20at%2011.40.03%E2%80%AFPM.png?alt=media&amp;token=f994a14a-892d-472b-9fdc-793d66c3b61c" alt=""><figcaption><p>Ensure that "method" and "bundle" params" are correct</p></figcaption></figure>

</details>
{% endstep %}

{% step %}

### Simulate your Batch

Press **\[Simulate Batch]** and ensure that the simulated outcomes are as expected.

{% hint style="info" %}
Cork Phoenix is designed with security as a core principle, going above and beyond on eliminating security footguns:

* Our escrow smart contract immutably enforce all business invariants at every step of execution.
* The protocol is architected such that all user actions can be fully simulated and reviewed as a single atomic transaction, enabling straightforward and reliable verification before committing anything onchain. (This also applies to legacy wallets without a builtin bundler.)
* Key smart contracts have easily identifiable addresses, making review straightforward.
  {% endhint %}
  {% endstep %}

{% step %}

### Send your Batch

Once you are satisfied with the simulation results, press **\[Send Batch]**.
{% endstep %}

{% step %}

### Sign and Submit your Batch

Follow the instructions from your connected wallet to sign and submit the batched transaction.
{% endstep %}
{% endstepper %}

***

### Step 5: Multisig Process on Batched Transaction

If you are **not** using a multisig, you may skip this step.

If you are using a multisig wallet, ask each co-signer/co-owner to follow these instructions:

{% stepper %}
{% step %}

### Select the Batched Transaction in the Wallet Queue

Select the queued transaction and open the list of actions or transactions within the batch.
{% endstep %}

{% step %}

### Verify the Calldata of each transaction in the batch

Each cosigner copies the calldata of each action or transaction into a [safe decoder](https://safe.swiss-knife.xyz/calldata-decoder), and verifies that the decoded data contains the correct amounts and addresses.

DO NOT CONTINUE if they do not match!
{% endstep %}

{% step %}

### Approve the Batch

Each cosigner ensures that the batch's `messageHash` , displayed on their signing device (e.g. wallet hardware), matches completely with what is shown within the SAFE wallet app, before signing an approval of the batch.
{% endstep %}

{% step %}

### Execute the Batch

Once the threshold of cosigners have approved the batch, one of the wallet owners/cosigners has to execute the batched transaction and pay gas.
{% endstep %}
{% endstepper %}

***

### Step 6: Wait for Confirmation and Verify token balances

Once the batched transaction is confirmed, follow your wallet-specific instructions to add both cPT (Cork [Principal Token](/core-concepts/principal-token)) address and cST (Cork [Swap Token](/core-concepts/swap-token)) address into your wallet to check their balances.

The cPT address and cST address may be obtained by calling `CorkPoolManager.shares(poolId)` with the [Cork Pool](/core-concepts/cork-pool) id, via either:

* **Etherscan (Closed source):** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F42)
* **Blockscout (Open source):** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0xde963ff1)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"shares(bytes32)(address corkPrincipalToken, address corkSwapToken)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

***


# Mint Tokens (without dApp or Batch-Capable Wallet)

How to Mint Swap Token and Principal Token using a wallet that does not support atomic batch transactions

Provide cover by depositing [**collateral assets**](/core-concepts/collateral-asset) into a [**Cork Pool**](/core-concepts/cork-pool) to mint shares of Cork [**Principal Token**](/core-concepts/principal-token) (cPT) and Cork [**Swap Token**](/core-concepts/swap-token) (cST), without using our dApp.

This **"Mint" operation** on Cork:

* deposits [**Collateral Asset**](/core-concepts/collateral-asset) into one of many [**Cork Pools**](/core-concepts/cork-pool)
* mints share tokens (i.e. increases circulating supply of cPT & cST tokens of that Cork Pool)

***

## **How to Mint Shares of a Cork Pool via an Escrowed Deposit**

{% hint style="info" %}
You will be performing a trust-minimized escrowed operation. This is enforced by our escrow smart contract (CorkAdapter) to ensure that the end-user's desired intent is fulfilled properly with the expected outcomes. A deadline also ensures that your tokens are never stuck in an inconsistent state.
{% endhint %}

**Prerequisites:**

* The Cork Pool's market id (bytes32).
  * A balance of [**Collateral Asset**](/core-concepts/collateral-asset) **(CA)** that pertains to this [**Cork Pool**](/core-concepts/cork-pool).
* An EoA or Legacy wallet that does not support *atomic batching —* i.e ***not** an* [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet such as a SAFE Wallet or an Account-Abstraction Wallet.
  * For your own safety, you are advised to use a wallet that supports clear signing (i.e. some form of calldata and bundle visualization) that improves opsec.
* Completed a due diligence audit of the `safeDeposit` function on `Line 126` of the escrow manager contract (CorkAdapter) at its live deployment address via either:
  * **Sourcify.dev:** <https://repo.sourcify.dev/1/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407>
  * **Blockscout:** <https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=contract_source_code>
  * **Github:** [Link](https://github.com/Cork-Technology/phoenix/blob/d8d469b0189184179f64ab6e4410b1cda8fcace4/contracts/periphery/CorkAdapter.sol#L126-L168)

***

{% hint style="info" %}
These instructions are for wallets that do not support atomic batch transactions. If you have an *atomic* EIP-5792 capable wallet such as SAFE Wallet by safe.global (previously Gnosis SAFE), it is recommended to use [this guide](/user-guides/provide-liquidity/mint-tokens-without-dapp) instead as it requires fewer steps and saves gas.
{% endhint %}

### Step 1: Open your Chain Explorer's Transaction Builder

Before we begin, check that you’re using the latest version of your browser by visiting [whatismybrowser.com](https://www.whatismybrowser.com/). If it’s not up to date, please update your browser to the latest version before continuing.

Connect your wallet to a Blockchain Explorer's Transaction Builder through this link: <https://eth.blockscout.com/token/0x9D39A5DE30e57443BfF2A8307A4256c8797A3497?tab=write_contract>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FGrOYtsUKdtGhvw3OZ42d%2Fimage.png?alt=media&amp;token=cd6f2114-f7c1-4436-b213-dfbbff7b4f62" alt=""><figcaption><p>Press [Connect Wallet]</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FUWqCABu7gxBnf7ypWAq4%2Fimage.png?alt=media&amp;token=1c5c675d-7e6f-4e5a-9556-44198554a8f7" alt=""><figcaption><p>Ensure that the right wallet address is connected</p></figcaption></figure>

***

### Step 2: Perform Transaction #1 – Allow spending of Collateral Assets by the Escrow Contract

Perform the 1st transaction to allow spending of collateral assets by our trust-minimized escrow manager contract (CorkAdapter):

* **Contract Address:** `<ERC20 token address of Collateral Asset>`
* **Contract Method:** `approve`
  * **spender (escrow address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
  * **amount (of collateral):** \<wei amount of collateral asset to deposit, or allowance amount in wei>

<details>

<summary>How to obtain ERC20 token address of Collateral Asset</summary>

The [Collateral asset](/core-concepts/collateral-asset) (CA) address and [Reference asset](/core-concepts/reference-asset) (REF) address may be obtained by calling `CorkPoolManager.assets(poolId)` with the [Cork Pool](/core-concepts/cork-pool) id, via either:

* **Etherscan (Closed source):** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F4)
* **Blockscout (Open source):** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0x9fda5b66)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"assets(bytes32)(address collateralAsset, address referenceAsset)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

</details>

By following these instructions:

{% stepper %}
{% step %}

### Calculate the allowed amount in wei

To calculate the right wei-amount of collateral asset (CA), first obtain the token decimals of the collateral asset from its ERC20 contract address, then multiply your amount by 10<sup>^</sup>(erc20\_decimal\_of\_CA).

For example, 10 USDC (which has 6 decimals) is represented as![](data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==) $$10 \times 10^{6}$$ , which is `10 000 000` in wei-amount.

Use a unit converter that allows you to adjust the token decimals, such as:\
[https://converter.swiss-knife.xyz/eth](https://converter.swiss-knife.xyz/eth?wei=1000000000000000000)

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FGpRA5QW80pvPki3udYlI%2FScreenshot%202026-01-12%20at%204.21.03%E2%80%AFPM.png?alt=media&amp;token=3ab03497-52a0-4fc3-ac7e-5d3c2dd2634c" alt=""><figcaption><p>Input the amount under "Ether", adjust the decimals of "10^6", then press [Copy] button to its right.</p></figcaption></figure>
{% endstep %}

{% step %}

### Enter ERC20 Address of Collateral Asset

Press the search button on the top-right of the Blockchain Explorer page and input the Collateral Asset's ERC20 address as shown below.

* **Search by address:** `<ERC20 token address of Collateral Asset>`

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FO05sbvjLq0c9mz22WBy9%2Fimage.png?alt=media&amp;token=03d9fbb2-df76-479b-a0a3-cfa341dd9568" alt=""><figcaption><p>Search for ERC20 token address &#x26; Select the first result</p></figcaption></figure>
{% endstep %}

{% step %}

### Input Transaction #1 Details

Press \[Contract], then \[Read/Write contract], then \[Write].

Then scroll down to look for `approve` , expand the section, and input these details:

* **Contract Method:** `approve`
* **spender (address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **amount (uint256):** \<allowance amount in wei, copied from above>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FSigCavtpQ7oSE8MjIP1P%2FScreenshot%202026-01-21%20at%203.04.07%E2%80%AFAM.png?alt=media&amp;token=4a223292-7482-4ae2-8bc6-ffdb7f52a9ec" alt=""><figcaption><p>Input transaction details under the contract method</p></figcaption></figure>
{% endstep %}

{% step %}

### Sign and Submit Transaction #1

Unlock your connected wallet, and press **\[Write]**, then review and sign transaction #1 on your connected wallet.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FHJ8EgIE3q5W658ltO9Uk%2FScreenshot%202026-01-21%20at%203.10.33%E2%80%AFAM.png?alt=media&amp;token=cc43165c-6b29-4f72-9478-814ad324552a" alt=""><figcaption><p>Press [Confirm]</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FAAAYvLP2iT8BPLXqI5GC%2FScreenshot%202026-01-21%20at%203.06.49%E2%80%AFAM.png?alt=media&amp;token=e34e6da4-7308-4811-8a59-75e8a7ae1ad7" alt=""><figcaption><p>Wait for the transaction to complete</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FVM8dEV4rVe6UtEl6wIVk%2FScreenshot%202026-01-21%20at%203.07.06%E2%80%AFAM.png?alt=media&amp;token=759a94fc-f6c2-47f4-a352-07e30f693ffd" alt=""><figcaption><p>Close this popup</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 3: Perform Transaction #2 – Deposit/Mint with escrowed assets

Perform the 2nd transaction to mint cPT (Cork [Principal Token](/core-concepts/principal-token)) and cST (Cork [Swap Token](/core-concepts/swap-token)) by depositing escrowed collateral assets into a Cork Pool:

* **Contract Address:** `0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`
* **Contract Method:** `multicall`
  * **Send native ETH:** `0`
  * **bundle:**
    * **#1 Call** (tuple):
      * **to** (address): `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
        * The `to` address is the call target, which is the escrow contract address
      * **data** (bytes):
        * The `calldata` as copied from the [erc20TransferFrom step](#input-erc20transferfrom-parameters).
      * **value** (uint256): `0`
        * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
      * **skipRevert** (bool): `false`,
        * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To reduce gas wastage, we must revert if the ERC20 transfer-to-escrow fails.
      * **callbackHash** (bytes32): `0x0000000000000000000000000000000000000000000000000000000000000000`
        * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.
    * **#2 Call** (tuple):
      * **to** (address): `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
        * The `to` address is the call target, which is the escrow contract address
      * **data** (bytes):
        * The `calldata` as copied from the [safeDeposit step](#input-safedeposit-parameters).
      * **value** (uint256): `0`
        * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
      * **skipRevert** (bool): `false`,
        * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To protect escrowed funds, we must also revert the ERC20 transfer-to-escrow if the deposit fails.
      * **callbackHash** (bytes32): `0x0000000000000000000000000000000000000000000000000000000000000000`
        * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.

By following these instructions:

{% stepper %}
{% step %}

### Input Erc20TransferFrom Parameters

Input these parameters into the "erc20TransferFrom" form linked [here](https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=write_contract#0xd96ca0b9):

* **Contract Method:** `erc20TransferFrom`
  * **params:**
    * **token** (address):
      * ERC20 token address of Collateral Asset
    * **receiver** (address)
      * The escrow contract address: `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
    * **amount** (uint256)
      * The wei amount of collateral assets to deposit. Must be **lesser or the same** as the wei amount allowed to be spent in [Step 2](#step-2-perform-transaction-1-allow-spending-of-collateral-assets-by-the-escrow-contract). Copy and paste this from a token [unit-converter](https://converter.swiss-knife.xyz/eth).
* Press **\[Copy calldata]**.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FMW3TXxorDAwcYu2O1DJL%2Fimage.png?alt=media&amp;token=25ae7fc0-cb03-4818-9245-a6dafbcf010e" alt=""><figcaption><p>Input transaction details and press [Copy calldata]</p></figcaption></figure>
{% endstep %}

{% step %}

### Optional: Verify copied Erc20TransferFrom calldata

Copy and paste the calldata into the Calldata Decoder linked [here](https://calldata.swiss-knife.xyz/decoder?address=0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407\&calldata=0x\&chainId=1), and press **\[Decode]** to verify your inputs:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F1GNQ8juyT9Tphl05LgpI%2Fimage.png?alt=media&amp;token=212a04c1-95ea-42d5-96d8-a4f7a108849b" alt=""><figcaption><p>Verify that the values displayed are correct</p></figcaption></figure>
{% endstep %}

{% step %}

### Optional: Calculate the deadline in seconds since epoch

Choose a time in the future using an [epoch-converter](https://epoch-converter.swiss-knife.xyz/). We recommend setting it **at least 1 hour from now** to allow sufficient time for cosigning. Since the bundle executes atomically, time-limited ERC-20 permits are unnecessary, allowing this timestamp to be set as far in the future as desired. Use this timestamp as the `deadline` in the next step.

{% hint style="info" %}
DO NOT attempt to retry this transaction before the deadline has passed.

Retrying earlier may result in duplicate operations, unintended consequences, or loss of funds.
{% endhint %}

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FySToACQkox4dHDTfFsD2%2FScreenshot%202026-01-12%20at%204.31.26%E2%80%AFPM.png?alt=media&amp;token=76977186-8037-4989-8740-b7750038f88a" alt=""><figcaption><p>Input your desired duration from now</p></figcaption></figure>

If missing, scroll to the right of the page to see the copy button:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FJ9GfVblSqwbhknq2Pb0w%2FScreenshot%202026-01-12%20at%204.31.30%E2%80%AFPM.png?alt=media&amp;token=cab350cd-a0ea-447f-bc2c-0046fe133b9d" alt=""><figcaption><p>Press [Copy] button</p></figcaption></figure>
{% endstep %}

{% step %}

### Input SafeDeposit Parameters

Input these parameters into the "safeDeposit" form linked [here](https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=write_contract#0x41881406):

* **Contract Method:** `safeDeposit`
  * **params:**
    * **poolId** (bytes32)
      * The cork pool market id
    * **collateralAssetsIn** (uint256)
      * The wei amount of collateral assets to deposit. ~~Use \[Max]~~ or input **the same** wei amount being transferred to escrow in the [erc20TransferFrom Step](#input-erc20transferfrom-parameters).
    * **receiver** (address)
      * Your wallet address. Or the address to which shares (cST & cPT) will be minted.
    * **minCptAndCstSharesOut** (uint256)
      * The amount (non-denominated in wei) of Collateral Asset in the [erc20TransferFrom Step](#input-erc20transferfrom-parameters), multiplied by 10<sup>18</sup>.
      * This guarantees the minimum amount of shares (cST & cPT) to receive.
    * **deadline** (uint256)
      * The deadline by which the transaction must be completed. Use **\[Now+1h]** or copy from an [epoch-converter](https://epoch-converter.swiss-knife.xyz/).
* Press **\[Copy calldata]**.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FAuHx1KIJaYQFZkFg1Gkq%2FScreenshot%202026-01-20%20at%2010.28.39%E2%80%AFPM.png?alt=media&amp;token=830a253f-355a-4820-8090-0fd0164918e7" alt=""><figcaption><p>Input transaction details and press [Copy calldata]</p></figcaption></figure>

{% hint style="info" %}
DO NOT attempt to retry this transaction before the deadline has passed.

Retrying earlier may result in duplicate operations, unintended consequences, or loss of funds.
{% endhint %}
{% endstep %}

{% step %}

### Optional: Verify copied SafeDeposit calldata

Copy and paste the calldata into the Calldata Decoder linked [here](https://calldata.swiss-knife.xyz/decoder?address=0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407\&calldata=0x\&chainId=1), and press **\[Decode]** to verify your inputs:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fbpn47ozkh3MmVXyxNKuH%2FScreenshot%202026-01-21%20at%202.14.07%E2%80%AFAM.png?alt=media&amp;token=100a15d7-3b33-480f-b745-64e5ccc01b9d" alt=""><figcaption><p>Verify that the values displayed are correct</p></figcaption></figure>
{% endstep %}

{% step %}

### Enter Address of Bundler3 contract

{% hint style="info" %}
A Bundler contract is analogous to a Router contract, with the added guarantee that each step of the execution is explicitly defined rather than implicit.

This reduces the need to absolutely verify and place trust in esoteric code when interacting with smart contracts.

By ensuring that each step is verifiable by a mainstream enduser and his wallet, this system achieves greater end-to-end transparency and security.
{% endhint %}

Press the search button on the top-right of the Blockchain Explorer page and input the [Bundler3 contract address](https://docs.morpho.org/get-started/resources/addresses/#bundlers) as shown below.

* **Search by address:** `0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fgl8thEfMps5xEkmMUzHk%2Fimage.png?alt=media&amp;token=857d48ad-cfb0-4c43-af78-ebc2a5b53bca" alt=""><figcaption><p>Search for Bundler3 contract address &#x26; Select the first result</p></figcaption></figure>
{% endstep %}

{% step %}

### Input Transaction #2 Details

Press \[Contract], then \[Read/Write contract], then \[Write].

Then scroll down to look for `multicall` , expand the section, and input these details:

* **Contract Method:** `multicall`
* **Send native ETH:** `0`
* **bundle:**
  * **#1 Call** (tuple):
    * **to** (address): `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
      * The `to` address is the call target, which is the escrow contract address
    * **data** (bytes):
      * The `calldata` as copied from the [erc20TransferFrom step](#input-erc20transferfrom-parameters).
    * **value** (uint256): `0`
      * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
    * **skipRevert** (bool): `false`,
      * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To reduce gas wastage, we must revert if the ERC20 transfer-to-escrow fails.
    * **callbackHash** (bytes32): `0x0000000000000000000000000000000000000000000000000000000000000000`
      * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.
  * **#2 Call** (tuple):
    * **to** (address): `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
      * The `to` address is the call target, which is the escrow contract address
    * **data** (bytes):
      * The `calldata` as copied from the [safeDeposit step](#input-safedeposit-parameters).
    * **value** (uint256): `0`
      * The `value` is the wei amount of ETH or native token to forward. Set to 0 (none) in this case.
    * **skipRevert** (bool): `false`,
      * If `skipRevert` is true, other planned calls will continue executing even if this call reverts. To protect escrowed funds, we must also revert the ERC20 transfer-to-escrow if the deposit fails.
    * **callbackHash** (bytes32): `0x0000000000000000000000000000000000000000000000000000000000000000`
      * The `callbackHash` should be set to the hash of the reenter bundle data. Set to 0x0 (none) in this case.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F9DHolP932tIJEBxQAUbR%2FScreenshot%202026-01-21%20at%204.20.11%E2%80%AFAM.png?alt=media&amp;token=562d55e5-89de-41b5-8c64-1b23636e59ab" alt=""><figcaption><p>Input transaction details under the contract method</p></figcaption></figure>
{% endstep %}

{% step %}

### Sign and Submit Transaction #2

Unlock your connected wallet, and press **\[Simulate]**.

{% hint style="info" %}
Cork Phoenix is designed with security as a core principle, going above and beyond on eliminating security footguns:

* Our escrow smart contract immutably enforce all business invariants at every step of execution.
* The protocol is architected such that all user actions can be fully simulated and reviewed as a single atomic transaction, enabling straightforward and reliable verification before committing anything onchain. (This includes legacy wallets without a builtin bundler.)
* Key smart contracts have easily identifiable addresses, making review straightforward.
  {% endhint %}

When you are satisfied with the simulation results, unlock your connected wallet again, and press **\[Write]**. Then review and sign transaction #2 on your connected wallet.

{% hint style="info" %}
If you see a "Missing gas limit" error, your connected wallet may not be whitelisted. Press **\[Reject]** and then **\[Simulate]** to confirm this is the case.
{% endhint %}

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FqzDlO0LzrmqNJpukuFnS%2FScreenshot%202026-01-21%20at%204.28.27%E2%80%AFAM.png?alt=media&amp;token=05367e88-3f7e-4f43-839a-fb701dd6a211" alt=""><figcaption><p>Press [Confirm]</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FAAAYvLP2iT8BPLXqI5GC%2FScreenshot%202026-01-21%20at%203.06.49%E2%80%AFAM.png?alt=media&amp;token=e34e6da4-7308-4811-8a59-75e8a7ae1ad7" alt=""><figcaption><p>Wait for transaction to complete</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 4: Wait for Confirmation and Verify token balances

Once transaction #2 is confirmed, follow your wallet-specific instructions to add both cPT (Cork [Principal Token](/core-concepts/principal-token)) address and cST (Cork [Swap Token](/core-concepts/swap-token)) address into your wallet to check their balances.

The cPT address and cST address may be obtained by calling `CorkPoolManager.shares(poolId)` with the [Cork Pool](/core-concepts/cork-pool) id, via either:

* **Etherscan (Closed source):** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F42)
* **Blockscout (Open source):** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0xde963ff1)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"shares(bytes32)(address corkPrincipalToken, address corkSwapToken)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

***


# Unwind Tokens (without dApp)

How to Withdraw Collateral Assets early using an atomic EIP-5792 capable wallet

Withdraw collateral assets from a [Cork Pool](/core-concepts/cork-pool) before its expiry, by performing a redemption of both Cork [Principal Token](/core-concepts/principal-token) and Cork [Swap Token](/core-concepts/swap-token), without using our dApp.

This operation, called an "Unwind Mint":

* returns and burns shares (i.e. reduces circulating supply of cPT & cST tokens)
* withdraws [Collateral Asset](/core-concepts/collateral-asset)

## **How to Redeem Shares via an Escrowed Unwind-Mint**

{% hint style="info" %}
You will be performing a trust-minimized escrowed operation. This is enforced by our escrow manager contract (CorkAdapter) to ensure that the end-user's desired intent is fulfilled properly with the expected outcomes. A deadline also ensures that your tokens are never stuck in an inconsistent state.
{% endhint %}

**Prerequisites:**

* An *atomic* [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet such as SAFE Wallet by safe.global (previously Gnosis SAFE)
* Completed a due diligence audit of the `safeUnwindMint` function on `Line 216` of the escrow manager contract (CorkAdapter) at its live deployment address via either:
  * **Sourcify.dev:** <https://repo.sourcify.dev/1/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407>
  * **Blockscout:** <https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=contract_source_code>
  * **Github:** [Link](https://github.com/Cork-Technology/phoenix/blob/d8d469b0189184179f64ab6e4410b1cda8fcace4/contracts/periphery/CorkAdapter.sol#L216-L266)
* The Cork Pool's market id (bytes32).
  * A balance of Cork [Principal Token](/core-concepts/principal-token) (cPT) and Cork [Swap Token](/core-concepts/swap-token) (cST) that pertains to this [Cork Pool](/core-concepts/cork-pool).

***

{% hint style="info" %}
The instructions below are prepared using SAFE Wallet by SAFE Labs (safe.global), but also applies to any atomic [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet.
{% endhint %}

### Step 1: Open your Wallet's Transaction Builder

Open the SAFE Wallet's Transaction Builder using this link: <https://app.safe.global/share/safe-app?appUrl=https%3A%2F%2Fapps-portal.safe.global%2Ftx-builder>

<details>

<summary>Alternatively, you may navigate to the Transaction Builder by following these steps:</summary>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FShp9kVymmmf6AUCcdvGE%2FScreenshot%202026-01-12%20at%205.07.03%E2%80%AFPM.png?alt=media&amp;token=58820d76-22f0-4f72-ac8e-0468750ce61d" alt="SAFE Wallet Connect Button"><figcaption><p>a. Press [Connect]</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F0d6ys4PvG86IeVofSnz0%2FScreenshot%202026-01-12%20at%205.07.14%E2%80%AFPM.png?alt=media&amp;token=fd1973f2-a055-4f19-a567-94ae9e6ccb1b" alt="SAFE&#x27;s Connect Wallet Modal Window"><figcaption><p>b. Select your wallet</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FTmMkctReDsxoy389ulap%2FScreenshot%202026-01-12%20at%205.07.58%E2%80%AFPM.png?alt=media&amp;token=6be9323a-886e-4a30-afd9-4b8feb3b299b" alt="SAFE Wallet Sidebar"><figcaption><p>c. Press the [☰] hamburger button (if you do not see the sidebar), and select [New transaction].</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FQUaKiJepngj7htQapdFf%2FScreenshot%202026-01-12%20at%205.08.21%E2%80%AFPM.png?alt=media&amp;token=f3148c20-0762-4abc-80be-9e596ac1c751" alt="SAFE Wallet New Transaction Modal"><figcaption><p>d. Select [Transaction Builder].</p></figcaption></figure>

</details>

***

### Step 2: Add Transaction #1 – Allow spending of Principal Tokens by Escrow Manager Contract

Add the 1st transaction to allow the trust-minimized escrow manager contract (CorkAdapter) to spend your Cork Principal Tokens:

* **Enter Address:** `eth:<ERC20 token address of Cork Principal Token>`
* **Enter ABI:** Copy from [here](https://eth.blockscout.com/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2?tab=contract_abi)
* **To Address:** `<ERC20 token address of Cork Principal Token>`
* **Contract Method Selector:** `approve`
  * **spender (escrow contract):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
  * **amount (of cPT):** \<wei amount of principal tokens to redeem>

By following these instructions:

{% stepper %}
{% step %}

### Enter Address of Cork Principal Token to redeem

Cork [Principal Token](/core-concepts/principal-token) (cPT) represents a share of the [Cork Pool](/core-concepts/cork-pool).

Using the [Cork Pool](/core-concepts/cork-pool) id, the cPT address and cST address may be obtained by calling `CorkPoolManager.shares(poolId)` using either:

* **Etherscan Website:** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F42)
* **Blockscout Website:** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0xde963ff1)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"shares(bytes32)(address corkPrincipalToken, address corkSwapToken)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

Input the cPT address & ABI as shown below (prefixed with `eth:`). If the ABI does not load automatically, copy and paste the ABI from [here](https://eth.blockscout.com/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2?tab=contract_abi).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FjnPk5ph43Pw0CeELW4cm%2FScreenshot%202026-01-19%20at%206.20.09%E2%80%AFPM.png?alt=media&amp;token=6a6ad2de-d0ff-4bf0-bedc-0d750d4d7b82" alt=""><figcaption><p>Input cPT address &#x26; ABI</p></figcaption></figure>
{% endstep %}

{% step %}

### Calculate the amount in wei

Cork Principal Tokens have 18 decimals (i.e. 10^18 precision). To calculate the right wei-amount of principal tokens, use a unit converter such as:\
[https://converter.swiss-knife.xyz/eth](https://converter.swiss-knife.xyz/eth?wei=1000000000000000000)\
or\
<https://etherscan.io/unitconverter>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FGpRA5QW80pvPki3udYlI%2FScreenshot%202026-01-12%20at%204.21.03%E2%80%AFPM.png?alt=media&amp;token=3ab03497-52a0-4fc3-ac7e-5d3c2dd2634c" alt=""><figcaption><p>Press [Copy] button of "Wei"</p></figcaption></figure>
{% endstep %}

{% step %}

### Input the Transaction #1 Details

* **To Address:** `<ERC20 token address of Cork Principal Token>`
* **Contract Method Selector:** `approve`
* **spender (address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **amount (uint256):** \<wei amount of cPT to redeem copied from above>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FgArrWz7ln5gXdy4swLxa%2FScreenshot%202026-01-19%20at%206.24.07%E2%80%AFPM.png?alt=media&amp;token=575e8b47-6193-4244-b38f-e7afa701d999" alt=""><figcaption><p>Input transaction details under Transaction Information</p></figcaption></figure>
{% endstep %}

{% step %}

### Press \[+ Add new transaction]

Verify that transaction #1 has been added to the Transactions Batch.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fkx76ZTQJq1yxEpQIEjCe%2FScreenshot%202026-01-19%20at%206.30.57%E2%80%AFPM.png?alt=media&amp;token=99b5c4d7-e91e-45d9-999a-25924f1dc6a5" alt=""><figcaption><p>Press [Add new transaction]</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 3: Add Transaction #2 – Allow spending of Swap Tokens by Escrow Manager Contract

Add the 2nd transaction to allow the trust-minimized escrow manager contract (CorkAdapter) to spend your Cork Swap Tokens:

* **Enter Address:** `eth:<ERC20 token address of Cork Swap Token>`
* **Enter ABI:** Copy from [here](https://eth.blockscout.com/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2?tab=contract_abi)
* **To Address:** `<ERC20 token address of Cork Swap Token>`
* **Contract Method Selector:** `approve`
  * **spender (escrow contract):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
  * **amount (of cST):** \<wei amount of swap tokens to redeem>

By following these instructions:

{% stepper %}
{% step %}

### Obtain the Cork Swap Token address

Cork Swap Token (cST) is paired with their corresponding Cork Principal Token (cPT).

Using the [Cork Pool](/core-concepts/cork-pool) id, the cPT address and cST address may be obtained by calling `CorkPoolManager.shares(poolId)` using either:

* **Etherscan Website:** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F42)
* **Blockscout Website:** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0xde963ff1)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"shares(bytes32)(address corkPrincipalToken, address corkSwapToken)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`
    {% endstep %}

{% step %}

### Enter Address of Cork Swap Token to redeem

Input the cST address & ABI as shown below (prefixed with `eth:`). If the ABI does not load automatically, copy and paste the ABI from [here](https://eth.blockscout.com/token/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2?tab=contract_abi).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FjnPk5ph43Pw0CeELW4cm%2FScreenshot%202026-01-19%20at%206.20.09%E2%80%AFPM.png?alt=media&amp;token=6a6ad2de-d0ff-4bf0-bedc-0d750d4d7b82" alt=""><figcaption><p>Input cST address &#x26; ABI</p></figcaption></figure>
{% endstep %}

{% step %}

### Input the Transaction #2 Details

* **To Address:** `<ERC20 token address of Cork Swap Token>`
* **Contract Method Selector:** `approve`
* **spender (address):** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **amount (uint256):** \<wei amount of cST to redeem, copied from the wei amount of cPT in the previous step>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FgArrWz7ln5gXdy4swLxa%2FScreenshot%202026-01-19%20at%206.24.07%E2%80%AFPM.png?alt=media&amp;token=575e8b47-6193-4244-b38f-e7afa701d999" alt=""><figcaption><p>Input transaction details under Transaction Information</p></figcaption></figure>
{% endstep %}

{% step %}

### Press \[+ Add new transaction]

Verify that transaction #2 has been added to the Transactions Batch.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Faxi30f3kiNWR0GdOeVca%2FScreenshot%202026-01-19%20at%207.02.05%E2%80%AFPM.png?alt=media&amp;token=7773a1d1-1c14-43aa-9dc3-180f41d66180" alt=""><figcaption><p>Press [Add new transaction]</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 4: Add Transaction #3 – Request an escrowed Unwind-Mint

Add the 3rd transaction to withdraw collateral assets from a Cork Pool by redeeming both cPT (Cork Principal Token) and cST (Cork Swap Token):

* **Enter Address:** `eth:0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **Enter ABI:** Copied from [here](https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=contract_abi)
* **To Address:** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **Contract Method Selector:** `safeUnwindMint`
  * **params:** `[comma separated values as below...]`
    * "\<poolId>",
      * The cork pool market id
    * "\<cptAndCstSharesIn>",
      * The wei amount of shares to redeem. Copied from the previous step.
    * "\<ownerAddress>",
      * Your wallet address (or the address that owns the cPT and cST shares to be burned).
    * "\<receiverAddress>",
      * Your wallet address (or the address to which collateral assets and any excess shares will be sent).
    * "\<minCollateralAssetsOut>",
      * The minimum wei amount of collateral assets to receive from the unwind operation. From [unit-converter.](https://converter.swiss-knife.xyz/eth?wei=1000000000000000000)
    * "\<deadline>"
      * The numeric deadline by which the transaction must be completed. From [epoch-converter](https://epoch-converter.swiss-knife.xyz/).
  * **Example params:**

```
[
"0x0000000000000000000000000000000000000000000000000000000000000000", 
"1000000000000000000", 
"0xd01F187CFBB86b0422536814f58f43d1806D49Cf", 
"0xd01F187CFBB86b0422536814f58f43d1806D49Cf", 
"1000000000000000000", 
"1768293967"
]
```

By following these instructions:

{% stepper %}
{% step %}

### Enter Address or ENS Name of CorkAdapter address

Input the CorkAdapter contract address & ABI as shown below. If the ABI does not load automatically, copy and paste the ABI from [here](https://eth.blockscout.com/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407?tab=contract_abi).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F1kY64aO7Ky1KBT74iIkY%2FScreenshot%202026-01-19%20at%207.22.01%E2%80%AFPM.png?alt=media&amp;token=870822ab-a5a9-4ea6-ad52-e9a7a91ba1c2" alt=""><figcaption><p>Input CorkAdapter address</p></figcaption></figure>
{% endstep %}

{% step %}

### Calculate the deadline in seconds since epoch

Choose a future timestamp using an [epoch-converter](https://epoch-converter.swiss-knife.xyz/). We recommend setting it **at least 1 hour from now** to allow sufficient time for cosigning. Since the batch executes atomically, offline ERC-20 permits are unnecessary, allowing this `deadline` to be set as far in the future as desired. Use this timestamp as the `deadline` in the next step.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FySToACQkox4dHDTfFsD2%2FScreenshot%202026-01-12%20at%204.31.26%E2%80%AFPM.png?alt=media&amp;token=76977186-8037-4989-8740-b7750038f88a" alt=""><figcaption><p>Input your desired duration from now</p></figcaption></figure>

If missing, scroll to the right of the page to see the copy button:

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FJ9GfVblSqwbhknq2Pb0w%2FScreenshot%202026-01-12%20at%204.31.30%E2%80%AFPM.png?alt=media&amp;token=cab350cd-a0ea-447f-bc2c-0046fe133b9d" alt=""><figcaption><p>Press [Copy] button</p></figcaption></figure>
{% endstep %}

{% step %}

### Input the Transaction #3 Details

* **To Address:** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`
* **Contract Method Selector:** `safeUnwindMint`
  * **params:** `[comma separated values as below...]`
    * "\<poolId>",
      * The cork pool market id
    * "\<cptAndCstSharesIn>",
      * The wei amount of shares to redeem. Copied from the previous step.
    * "\<ownerAddress>",
      * Your wallet address (or the address that owns the cPT and cST shares to be burned).
    * "\<receiverAddress>",
      * Your wallet address (or the address to which collateral assets and any excess shares will be sent).
    * "\<minCollateralAssetsOut>",
      * The minimum wei amount of collateral assets to receive from the unwind operation. From [unit-converter.](https://converter.swiss-knife.xyz/eth?wei=1000000000000000000)
    * "\<deadline>"
      * The numeric deadline by which the transaction must be completed. From [epoch-converter](https://epoch-converter.swiss-knife.xyz/).

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FtmPtQCZZGS6vZUSweF2Z%2FScreenshot%202026-01-19%20at%207.25.05%E2%80%AFPM.png?alt=media&amp;token=82ba028e-0345-4de9-8b1d-aabe4dc6777e" alt=""><figcaption><p>Input transaction details under Transaction Information</p></figcaption></figure>
{% endstep %}

{% step %}

### Press \[+ Add new transaction]

Verify that transaction #3 has been added to the Transactions Batch.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Flu0NsLP1Umt2dSxwL9Eq%2FScreenshot%202026-01-19%20at%207.25.31%E2%80%AFPM.png?alt=media&amp;token=34567e38-5ce2-41f3-ae35-aadc19dbfac9" alt=""><figcaption><p>Press [Add new transaction]</p></figcaption></figure>
{% endstep %}
{% endstepper %}

***

### Step 4: Create, Review & Simulate Batch

Press \[Create Batch] and follow these instructions:

{% stepper %}
{% step %}

### Review and Confirm batch

Make sure that you see this "Review and Confirm" screen.

**Important:** Enable ***atomic batch*** if asked by your [EIP-5792](https://www.eip5792.xyz/introduction) capable wallet. Using non-atomic batch mode can lead to lost of funds!

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FtU7tdDR6bLcxbOfvI5cw%2FScreenshot%202026-01-19%20at%207.29.12%E2%80%AFPM.png?alt=media&amp;token=350199c1-50f8-46b7-b609-75b89e7593fd" alt=""><figcaption><p>Ensure that there are 3 items in the Atomic Batch</p></figcaption></figure>
{% endstep %}

{% step %}

### Verify each transaction in your batch

<details>

<summary>An example of each transaction in the batch:</summary>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FkvfcIbGJqOeBYpYnA84Y%2FScreenshot%202026-01-19%20at%207.30.04%E2%80%AFPM.png?alt=media&amp;token=f1380c7f-0535-4ad2-b0ce-2869247b9ec1" alt=""><figcaption><p>Ensure that "method", "spender" and "amount" is correct</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FZO05X7SSHaF9CgC1RF6l%2FScreenshot%202026-01-19%20at%207.30.44%E2%80%AFPM.png?alt=media&amp;token=f68b2b56-b58f-42bf-9917-9fb8d2d8bbcb" alt=""><figcaption><p>Ensure that "method", "spender" and "amount" is correct</p></figcaption></figure>

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FB5bA75f25vPhTCqUcroY%2FScreenshot%202026-01-19%20at%207.31.42%E2%80%AFPM.png?alt=media&amp;token=0fd3027a-5a52-4777-9e21-fce240d6827a" alt=""><figcaption><p>Ensure that "to", "method", and "params" are correct</p></figcaption></figure>

</details>
{% endstep %}

{% step %}

### Simulate the batch

Press \[Simulate Batch] and ensure that the simulated outcomes are as expected.
{% endstep %}

{% step %}

### Send Batch

Once the simulation has completed successfully, press \[Send Batch].
{% endstep %}
{% endstepper %}

***

### Step 5: Sign and Execute transaction

Ask each co-signer/co-owner to follow these instructions:

{% stepper %}
{% step %}

### Select the Batch in the Wallet Queue

Select the batch and open the details of each transaction within the batch.
{% endstep %}

{% step %}

### Verify the Calldata of each transaction in the batch

Each cosigner copies the calldata of each transaction into a [safe decoder](https://safe.swiss-knife.xyz/calldata-decoder), and verifies that the decoded data contains the correct amounts and addresses.

DO NOT CONTINUE if they do not match!
{% endstep %}

{% step %}

### Approve the Batch

Each cosigner ensures that the batch's `safeTxHash` (or EIP-712 `messageHash`), displayed on their signing device (e.g. wallet hardware), matches completely before signing an approval of the batch.
{% endstep %}

{% step %}

### Execute the Batch

Once the threshold of cosigners have approved the batch, one of the wallet owners/signers has to execute the transaction (using the wallet) and pay gas.
{% endstep %}
{% endstepper %}

***

### Step 6: Wait for Confirmation and Verify token balances

Once the batch transaction is confirmed, follow your wallet-specific instructions to check your collateral asset balance.

Using the [Cork Pool](/core-concepts/cork-pool) id, the [Collateral asset ](/core-concepts/collateral-asset)(CA) address and [Reference asset](/core-concepts/reference-asset) (REF) address may be obtained by calling `CorkPoolManager.assets(poolId)` using either:

* **Etherscan Website:** [**Link**](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC#readProxyContract#F4)
* **Blockscout Website:** [**Link**](https://eth.blockscout.com/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC?tab=read_proxy\&source_address=0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244#0x9fda5b66)
* **Foundry Command Line:**
  * `cast call`\
    `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`\
    `"assets(bytes32)(address collateralAsset, address referenceAsset)"`\
    `<POOL_ID>`\
    `--rpc-url https://eth.drpc.org`

***


# OTC trading of Swap Tokens

In order to lock in the fixed yield from underwriting a particular market, the liquidity provider must sell their Cork Swap Tokens in exchange for a premium. Meanwhile, for hedgers to gain access to Swap Tokens, they need a mechanism to transfer their premium payment in exchange for the Swap Tokens. Airswap OTC is battle tested tool which enables such transactions to be made. This guide will explain how to make and take orders on Airswap OTC.

## Making an order

1. Navigate to <https://www.airswap.xyz/otc> and press start now
2. Press "make an order"

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FARZmCYmZLyAVKJQ5d3SE%2Fimage.png?alt=media&amp;token=483b0d19-5251-44ef-85ea-e0ebe207d47a" alt=""><figcaption></figcaption></figure>

3. Press "From - Select" and insert the token address of the Cork Swap Token. This can be collected in the dapp in the "Airswap Instructions" page in the mint flow, but can be confirmed separately by the Cork team.
4. Press "To - ETH" and select the desired payment token, for example USDC.
5. Press "For" and select "Specific Taker", to enable only one counterparty to take the order. Insert the wallet address of the taker.
6. Press "Expires in" and adjust (recommended to approximately 3 days) to enable the taker to complete the order.
7. Press Continue to advance to the next screen.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fp77jYAW46kkxt3KmzwfG%2Fimage.png?alt=media&amp;token=f692ab1b-64f7-4435-aa1a-989d6cb5c037" alt=""><figcaption></figcaption></figure>

8. Press Sign to initiate token approval. The tokens will remain in your wallet but will be approved for spending and will be transferred from your wallet when the order is taken.
9. After approval, press "Sign" again to create the order. This will take you to a final order confirmation page where you can "copy link" to the order.
10. Send the order link to the counterparty purchasing the Swap Tokens so they can take the order.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F0ztB8aub3LLk6zKgJYXR%2Fimage.png?alt=media&amp;token=bf99f07b-8769-482f-a763-2a9d53be93a0" alt=""><figcaption></figcaption></figure>

## Taking an order

After receiving the link to an order, perform the following steps:<br>

1. Review details

Review the following details of the trade:

A. Correct contract address of the Swap Token\
B. Correct payment token\
C. Correct price to be paid

If the above are correct, proceed to press “Approve” which will trigger a token approval for the payment token.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2F2zxNGmvqRjR1GlYbaTlX%2Fimage.png?alt=media&amp;token=88fe49e1-073f-4269-9752-f43d228b537a" alt=""><figcaption></figcaption></figure>

2. Take the order

Following the approval of the payment token, you are ready to execute the trade by pressing Take which will trigger another transaction in your wallet.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2FIVH8QgZHWQOzjQO8VUsm%2Fimage.png?alt=media&amp;token=e020d2ff-6314-4f52-a3ca-b196f4317a35" alt=""><figcaption></figcaption></figure>

3. Swap completed

After the transaction is completed, your Swap Tokens will directly arrive in your wallet.

<figure><img src="https://848218386-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHnnwcaUXAmdwnwY7RKLX%2Fuploads%2Fdv7cePesbbyw5VHq2gIh%2Fimage.png?alt=media&amp;token=fd47500b-492c-4fd2-aec8-a2cc39e00ad3" alt=""><figcaption></figcaption></figure>


# Frequently Asked Questions

Common questions about Cork Protocol — how it works, key mechanics, and getting started

## Protocol Mechanics

#### What is a Cork Pool?

A Cork Pool is the core primitive of Cork Protocol. It pairs a Collateral Asset with a Reference Asset and issues two tokens on deposit: Cork Principal Token and Cork Swap Token. See [Cork Pool](/core-concepts/cork-pool) for the full explanation.

#### What is the difference between a Cork Principal Token and a Cork Swap Token?

**Cork Principal Token** represents your principal claim on the pool. At expiry, you redeem Cork Principal Tokens for your proportional share of pool assets. **Cork Swap Token** gives you the right to exercise — exchange Reference Asset + Cork Swap Token for Collateral Asset before expiry. They are complementary: Cork Principal Tokens are for underwriters earning yield, Cork Swap Tokens are for those seeking coverage.

#### Why do Cork Principal Tokens and Cork Swap Tokens use 18 decimals regardless of the underlying token?

All Cork pool share tokens are standardized to 18 decimals for consistency. Even if the Collateral Asset uses different decimals (e.g., USDC with 6), the protocol normalizes internally. This simplifies integration and prevents decimal-mismatch errors.

#### What determines the price of a Cork Swap Token or Cork Principal Token?

Current Cork markets trade through OTC limit orders, where pricing is set between two counterparties and executed onchain. The prices of Cork Swap Tokens and Cork Principal Tokens are inversely related — both add up to 1 Collateral Asset. If the premium (Cork Swap Token price) increases, the Cork Principal Token price decreases proportionally.

#### What is the Exchange Rate?

The Exchange Rate determines how many Reference Assets correspond to each Cork Swap Token when exercising. It accounts for yield differentials between the Collateral Asset and Reference Asset. For yield-bearing pairs (e.g., wstETH/ETH), the rate adjusts continuously to prevent yield from being arbitraged out of the pool at the expense of Cork Principal Token holders.

#### What is the Premium?

The premium is the annualized cost that Cork Swap Token holders pay to Cork Principal Token holders for coverage. For example, a 4% annual premium on a 3-month expiry would cost approximately 0.01 Collateral Asset per Cork Swap Token (4% / 4 quarters).

#### What happens when a Cork Swap Token expires?

At expiry, the Cork Swap Token can no longer be exercised and has no further value. The Cork Principal Token can be used to redeem the remaining assets in the Cork Pool via the Redeem operation.

#### What is a MarketId?

A MarketId is the `keccak256` hash of all 8 fields in the Market struct. It uniquely identifies a Cork Pool. The same Market parameters always produce the same MarketId on any chain. See [CorkPoolManager](/developers/contract-reference/cork-pool-manager#marketid-computation) for computation details.

***

## Risk & Coverage

#### What is a price deviation event?

A price deviation event occurs when a pegged asset — such as a stablecoin or liquid staking token — trades below its intended value due to market volatility, liquidity issues, or external shocks. Some deviations are temporary (e.g., USDC during the SVB collapse), while others are permanent (e.g., UST). Cork Swap Tokens allow holders to hedge against such events by guaranteeing exchange of the Reference Asset for the Collateral Asset regardless of market conditions.

#### What is duration risk and how does Cork address it?

Certain assets — vault shares, RWAs, bridge tokens — have limited secondary liquidity and primarily rely on redemption mechanisms with long delays (sometimes 40+ days). This exposes holders to duration risk: the gap between when you request a redemption and when you receive your assets. Cork Pools address this by enabling holders to acquire Cork Swap Tokens, which provide instant exchange of the Reference Asset for a liquid Collateral Asset, bypassing the redemption queue entirely.

#### What happens if the Reference Asset loses value relative to the Collateral Asset?

If the Reference Asset loses value relative to the Collateral Asset, Cork Swap Token holders can exercise their tokens to exchange Reference Asset for Collateral Asset at favorable terms. The Cork Swap Token becomes more valuable as the gap widens. Cork Principal Token holders bear this risk — at expiry, they receive a proportional share of pool assets, which may now include the impaired Reference Asset.

#### What happens if the Collateral Asset is impaired?

Both Cork Principal Token holders and (to some extent) Cork Swap Token holders are exposed to the performance of the Collateral Asset. If the Collateral Asset is impaired, Cork Principal Token holders may face a loss when they redeem. Cork Swap Token holders can still exercise, but they receive an impaired asset, which reduces the effective value of the coverage.

#### What are the risks of holding Cork Principal Tokens?

If there is an impairment of either the Reference Asset or the Collateral Asset, the Cork Principal Token holder bears the loss. If swaps are exercised, the pool's composition shifts from Collateral Asset toward Reference Asset — meaning at expiry, Cork Principal Token holders receive a mix of Collateral Asset and Reference Asset rather than pure Collateral Asset.

***

## Operations

#### What does "Unwind" mean?

Unwind means reversing a prior operation **before expiry**. **Unwind Deposit** returns Cork Principal Token + Cork Swap Token to recover the original Collateral Asset. **Repurchase** (Unwind Exercise) returns Collateral Asset to recover Reference Asset + Cork Swap Token from the pool. These operations are only available before the pool expires — after expiry, the only exit is Redeem.

#### What operations can I do before vs after expiry?

**Before expiry:** Deposit, Unwind Deposit, Exercise, Repurchase, Withdraw (exit Cork Principal Tokens for proportional Collateral Asset + Reference Asset). **After expiry:** Redeem only (same proportional exit, but uses the `redeem` contract function). In user-facing terms, both let Cork Principal Token holders claim their share — the contract distinguishes them based on whether the pool has expired. See the [Operations Table](/developers/contract-reference/cork-pool-manager#operations-table) for a complete reference.

#### How do fees work?

Fees are charged on Exercise and Repurchase operations only. They use 18-decimal precision (`1e18 = 1%`) with a maximum of 5%. Fees are configured per pool by governance. See [Fees](/core-concepts/fees) for calculation details and examples.

***

## About Cork

#### Why are you building Cork?

For DeFi to become the backbone of finance, trusted by large-scale institutions, it needs risk management infrastructure. We are building Cork to enable the creation of risk markets to help accelerate the adoption of DeFi.

#### Who is the team behind Cork?

Cork Protocol is built by Cork Protocol Inc. (Delaware) and operated by Cork Labs (Cayman Islands). The founding team are serial entrepreneurs with prior DeFi experience. Cork is backed by a16z CSX, OrangeDAO, Road Capital, BitGo, G-20, and Steakhouse Financial. Learn more at [cork.tech/about](https://www.cork.tech/about/).

#### Who would use Cork?

Cork is primarily designed for institutional and protocol users — asset managers, vault curators, lending protocols, and risk managers who need programmable risk infrastructure for their onchain assets.

#### Where is Cork Protocol deployed?

Cork is live on Ethereum mainnet and Sepolia testnet. All contracts use deterministic CREATE2 deployment, so addresses are identical across chains. See [Phoenix Deployments](/smart-contracts/phoenix-deployments) for the full address list.

#### Where can I see my positions?

On the Cork dApp at [app.cork.tech](https://app.cork.tech), connect your wallet and go to the Dashboard section.


# Audits

Information on smart contract risk and audits

## External Security Audits

Cork Phoenix has undergone independent security audits by two firms. All identified issues have been resolved or acknowledged.

### ChainSecurity

* **Scope:** Full protocol audit of [Cork Phoenix v0.5.0 (pre-release)](https://github.com/Cork-Technology/phoenix/commit/fe005f1be810c0f3f76fd8471fb199772cf1ac3a)
* **Date:** November 2025
* [**View Report (PDF)**](https://drive.google.com/file/d/1l16EzUj8GRDA19Ta5AC0LM4Z25In_xxD/view)

### Certora

* **Scope:** Full protocol audit and formal verification of [Cork Phoenix v1.1.0](https://github.com/Cork-Technology/phoenix/releases/tag/v1.1.0)
* **Date:** January 2026
* [**View Report (PDF)**](https://drive.google.com/file/d/1E7sFG41nPR8QFJpT_LK8sqeLsfPUVPtb/view)

{% hint style="info" %}
The Certora engagement included formal verification — a mathematical method that proves specific protocol properties hold under all possible inputs. The report covers 11 verified properties including accounting consistency, token backing, front-run resilience, and fee enforcement.
{% endhint %}

## Are smart contract upgrades audited?

Yes. Any changes to the code will undergo external review. Any smart contract upgrades will be audited.


# Phoenix Deployments

Official Cork Phoenix deployment addresses on Ethereum Mainnet

Cork Phoenix uses the Safe CREATE2 Deployer (`0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7`) for deterministic contract addresses across all supported chains.

{% hint style="warning" %}
Always verify contract addresses against this page or the [phoenix repo](https://github.com/Cork-Technology/phoenix) before interacting. Cork will never ask you to send funds to an address not listed here.
{% endhint %}

### Core Contracts

| Contract                         | Address                                                                                                                 | Role                                                                                              |
| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| CorkPoolManager (Proxy)          | [`0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC`](https://etherscan.io/address/0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC) | Singleton managing all pool states, deposits, withdrawals, swaps                                  |
| CorkPoolManager (Implementation) | [`0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244`](https://etherscan.io/address/0x1cCccCccCcCf9A60Fe57cd7CEf504d1DaaA78244) | UUPS upgradeable implementation                                                                   |
| CorkAdapter                      | [`0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407`](https://etherscan.io/address/0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407) | Periphery adapter providing slippage protection, deadline checks, and Morpho Bundler3 integration |
| SharesFactory                    | [`0xcCCCccCCCcCc1782617fe14A386AC910a20D4324`](https://etherscan.io/address/0xcCCCccCCCcCc1782617fe14A386AC910a20D4324) | Deploys Cork Principal Token (cPT) and Cork Swap Token (cST) pairs for each pool                  |

### Governance & Access Control

| Contract                      | Address                                                                                                                 | Role                                                                             |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| DefaultCorkController         | [`0xcCcCcCccCccbC06627F8aad7aAF13fe3a457f779`](https://etherscan.io/address/0xcCcCcCccCccbC06627F8aad7aAF13fe3a457f779) | Pool authorization, fee configuration, pause, whitelist, and treasury management |
| WhitelistManager (Proxy)      | [`0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE`](https://etherscan.io/address/0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE) | Global and market-specific access control for pool operations                    |
| ConstraintRateAdapter (Proxy) | [`0xCCcCcCcccCccEF378949D1a61ED2283C831AF03A`](https://etherscan.io/address/0xCCcCcCcccCccEF378949D1a61ED2283C831AF03A) | Chainlink oracle integration for constraint rate pricing                         |

### Timelock Contracts

All governance actions are subject to timelocks with the following delays:

| Contract                | Address                                                                                                                 | Delay             |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------- |
| TimelockUpgrade         | [`0x7CcCCCccCcc0b4c00d01f321035b8e4523eF8448`](https://etherscan.io/address/0x7CcCCCccCcc0b4c00d01f321035b8e4523eF8448) | 5 days (432,000s) |
| TimelockControllerAdmin | [`0x7CccCCccccCCe566CdAFFA9EF2CB245Ad5575c3b`](https://etherscan.io/address/0x7CccCCccccCCe566CdAFFA9EF2CB245Ad5575c3b) | 1 day (86,400s)   |
| TimelockOperational     | [`0x7CcCcCCcCccCC1d856F2994A66fAa7011F1A89D9`](https://etherscan.io/address/0x7CcCcCCcCccCC1d856F2994A66fAa7011F1A89D9) | 6 hours (21,600s) |

### External Dependencies

| Contract              | Address                                                                                                                 | Purpose                                                                               |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Morpho Bundler3       | [`0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245`](https://etherscan.io/address/0x6566194141eefa99Af43Bb5Aa71460Ca2Dc90245) | Atomic multi-operation execution; calls CorkAdapter for slippage-protected operations |
| Uniswap Permit2       | [`0x000000000022D473030F116dDEE9F6B43aC78BA3`](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | Signature-based token approvals                                                       |
| Safe CREATE2 Deployer | [`0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7`](https://etherscan.io/address/0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7) | Deterministic deployment across chains                                                |

## Active Markets

Each Cork Pool is identified by a `MarketId` and defines a pair of a Collateral Asset (CA) and a Reference Asset (REF). When a pool is active, users can Deposit CA to receive Cork Principal Token (cPT) and Cork Swap Token (cST).

{% hint style="info" %}
Market-specific cPT and cST token addresses are deployed per-pool by the SharesFactory. Query the CorkPoolManager's `shares(MarketId)` function to retrieve the cPT and cST addresses for a specific market.
{% endhint %}

### vbUSDC / sUSDe

| Parameter             | Value                                                                                                                            |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| MarketId              | *Query `CorkPoolManager.getId(collateralAsset, referenceAsset)` on-chain*                                                        |
| Collateral Asset (CA) | vbUSDC ([`0x53E82ABbb12638F09d9e624578ccB666217a765e`](https://etherscan.io/address/0x53E82ABbb12638F09d9e624578ccB666217a765e)) |
| Reference Asset (REF) | sUSDe ([`0x9D39A5DE30e57443BfF2A8307A4256c8797A3497`](https://etherscan.io/address/0x9D39A5DE30e57443BfF2A8307A4256c8797A3497))  |
| Morpho Oracle         | [`0x5D3159ba95dCdE02451a31fE68B08fB650b00458`](https://etherscan.io/address/0x5D3159ba95dCdE02451a31fE68B08fB650b00458)          |

{% hint style="info" %}
The MarketId is a `bytes32` hash derived from the Collateral Asset and Reference Asset addresses. Query it on-chain or compute it using `keccak256(abi.encode(collateralAsset, referenceAsset))`.
{% endhint %}

## Architecture Overview

Cork Phoenix uses a **singleton architecture** — all pool states are managed by a single CorkPoolManager contract. This differs from factory-per-pool patterns and provides gas efficiency and unified state management.

```
User --> Morpho Bundler3 --> CorkAdapter --> CorkPoolManager
                                                  |
                                            SharesFactory
                                             /        \
                                           cPT        cST
```

* **CorkPoolManager** is the core singleton. All operations (Deposit, Mint, Withdraw, Redeem, Swap, Exercise, and their Unwind/Other variants) are executed here.
* **CorkAdapter** provides slippage protection and deadline checks on CorkPoolManager operations. It is called by Morpho Bundler3, which provides atomic multi-operation execution.
* **DefaultCorkController** manages governance: pool creation, fee updates, pausing, treasury, and whitelist management.
* **WhitelistManager** enforces per-market access control on pool operations.

{% hint style="warning" %}
While you can interact with CorkPoolManager directly, it does not provide slippage or deadline protection. Use CorkAdapter for all production interactions.
{% endhint %}

## Source Code

The Cork Phoenix smart contracts are open source and available at [github.com/Cork-Technology/phoenix](https://github.com/Cork-Technology/phoenix).

For audit reports, see [Audits](/smart-contracts/audits).


# Quick Start

Query Cork Protocol data and simulate operations in minutes

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) and [Cork Swap Token](/core-concepts/swap-token) 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) — 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#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) — slippage-protected write operations for production use
* [CorkPoolManager](/developers/contract-reference/cork-pool-manager) — full query and operation reference
* [API Reference](/developers/api-reference) — historical data, market discovery, and limit orders


# Contract Reference

Cork Phoenix contract addresses, architecture overview, and detailed interface documentation

Cork Phoenix uses a singleton architecture. All pools are managed by a single CorkPoolManager contract. For write operations with slippage protection, use CorkAdapter. For read operations, query CorkPoolManager directly.

## Contract Addresses

All addresses are identical across Ethereum mainnet and supported chains, deployed via deterministic CREATE2.

| Contract              | Address                                      | Purpose                                             |
| --------------------- | -------------------------------------------- | --------------------------------------------------- |
| CorkPoolManager       | `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC` | All pool operations and state queries               |
| CorkAdapter           | `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407` | Safe wrappers with slippage and deadline protection |
| DefaultCorkController | `0xcCcCcCccCccbC06627F8aad7aAF13fe3a457f779` | Governance: pool creation, fees, pause control      |
| WhitelistManager      | `0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE` | Global and per-market access control                |
| ConstraintRateAdapter | `0xCCcCcCcccCccEF378949D1a61ED2283C831AF03A` | Oracle rate protection with daily change limits     |
| SharesFactory         | `0xcCCCccCCCcCc1782617fe14A386AC910a20D4324` | cPT/cST token pair deployment                       |

## Architecture

```
┌─────────────────────────────────┐
│         Your Application        │
└──────────┬──────────────────────┘
           │ write operations          read operations
           ▼                                │
┌─────────────────────┐                     │
│     CorkAdapter     │                     │
│  (slippage/deadline │                     │
│   protection)       │                     │
└──────────┬──────────┘                     │
           │                                │
           ▼                                ▼
┌──────────────────────────────────────────────┐
│              CorkPoolManager                  │
│  (singleton — all pool state and operations)  │
└──────────────────────────────────────────────┘
```

**For integrators:**

* Call **CorkAdapter** for all write operations (deposits, swaps, withdrawals, redeems). It adds slippage protection and deadline checks.
* Call **CorkPoolManager** directly for read operations (swap rate, pool balances, previews, max amounts).

## Detailed References

* [CorkAdapter](/developers/contract-reference/cork-adapter) — every safe operation with parameter details, code examples, and error handling
* [CorkPoolManager](/developers/contract-reference/cork-pool-manager) — query functions, preview functions, raw operations, and key protocol concepts
* [Admin & Governance](/developers/contract-reference/admin-and-governance) — DefaultCorkController, WhitelistManager, ConstraintRateAdapter, SharesFactory, and PoolShare tokens


# CorkAdapter

Slippage-protected write operations for Cork Protocol integration

**Address:** `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407` (same on all chains)

CorkAdapter wraps CorkPoolManager operations with slippage protection and deadline checks via Morpho Bundler3. Use this contract for all write operations in production integrations.

{% hint style="warning" %}
While you can interact with CorkPoolManager directly, it does not provide slippage or deadline protection. Use CorkAdapter for production integrations.
{% endhint %}

## Common Parameters

Every CorkAdapter function takes a params struct. These fields appear across all operations:

| Field      | Type      | Description                                                                                                      |
| ---------- | --------- | ---------------------------------------------------------------------------------------------------------------- |
| `poolId`   | `bytes32` | The MarketId identifying which Cork Pool to interact with                                                        |
| `receiver` | `address` | The address that receives the output tokens                                                                      |
| `deadline` | `uint256` | Unix timestamp after which the transaction reverts. A reasonable default is `block.timestamp + 300` (5 minutes). |

**Slippage fields** vary per operation — each function has either a `min*Out` field (minimum acceptable output) or `max*In` field (maximum acceptable input). Set these using the corresponding `preview*` function on CorkPoolManager, adjusted for your slippage tolerance. For example, for 0.5% slippage on a deposit:

```typescript
const expectedShares = await previewDeposit(marketId, amount)
const minSharesOut = expectedShares * 995n / 1000n // 0.5% slippage
```

***

## Deposit Operations

Provide Collateral Asset to receive Cork Principal Token (cPT) and Cork Swap Token (cST).

### safeDeposit

Deposit a specific amount of Collateral Asset and receive cPT + cST shares.

```solidity
function safeDeposit(SafeDepositParams calldata params) external
```

| Parameter               | Type      | Description                                                      |
| ----------------------- | --------- | ---------------------------------------------------------------- |
| `poolId`                | `bytes32` | MarketId                                                         |
| `collateralAssetsIn`    | `uint256` | Amount of Collateral Asset to deposit (in native token decimals) |
| `receiver`              | `address` | Receives the minted cPT and cST                                  |
| `minCptAndCstSharesOut` | `uint256` | Minimum cPT + cST shares to receive (18 decimals)                |
| `deadline`              | `uint256` | Transaction deadline                                             |

```typescript
import { encodeFunctionData } from 'viem'

const params = {
  poolId: MARKET_ID,
  collateralAssetsIn: parseUnits('100', 18), // 100 sUSDe
  receiver: userAddress,
  minCptAndCstSharesOut: expectedShares * 995n / 1000n,
  deadline: BigInt(Math.floor(Date.now() / 1000) + 300),
}

const data = encodeFunctionData({
  abi: corkAdapterAbi,
  functionName: 'safeDeposit',
  args: [params],
})
```

### safeMint

Mint a specific amount of cPT + cST shares, spending up to a maximum of Collateral Asset.

```solidity
function safeMint(SafeMintParams calldata params) external
```

| Parameter               | Type      | Description                                            |
| ----------------------- | --------- | ------------------------------------------------------ |
| `poolId`                | `bytes32` | MarketId                                               |
| `cptAndCstSharesOut`    | `uint256` | Exact amount of cPT + cST shares to mint (18 decimals) |
| `receiver`              | `address` | Receives the minted cPT and cST                        |
| `maxCollateralAssetsIn` | `uint256` | Maximum Collateral Asset to spend (native decimals)    |
| `deadline`              | `uint256` | Transaction deadline                                   |

***

## Unwind Deposit

Return cPT + cST to get Collateral Asset back. Available before expiry only.

### safeUnwindDeposit

Specify how much Collateral Asset you want back; burns the required cPT + cST.

```solidity
function safeUnwindDeposit(SafeUnwindDepositParams calldata params) external
```

| Parameter              | Type      | Description                                    |
| ---------------------- | --------- | ---------------------------------------------- |
| `poolId`               | `bytes32` | MarketId                                       |
| `collateralAssetsOut`  | `uint256` | Target Collateral Asset amount to receive      |
| `owner`                | `address` | Address that owns the cPT and cST being burned |
| `receiver`             | `address` | Receives the Collateral Asset                  |
| `maxCptAndCstSharesIn` | `uint256` | Maximum cPT + cST shares to burn               |
| `deadline`             | `uint256` | Transaction deadline                           |

### safeUnwindMint

Specify how many cPT + cST shares to burn; receive the corresponding Collateral Asset.

```solidity
function safeUnwindMint(SafeUnwindMintParams memory params) external
```

| Parameter                | Type      | Description                                                                 |
| ------------------------ | --------- | --------------------------------------------------------------------------- |
| `poolId`                 | `bytes32` | MarketId                                                                    |
| `cptAndCstSharesIn`      | `uint256` | Amount of cPT + cST shares to burn. Pass `type(uint256).max` to redeem all. |
| `owner`                  | `address` | Address that owns the shares                                                |
| `receiver`               | `address` | Receives the Collateral Asset                                               |
| `minCollateralAssetsOut` | `uint256` | Minimum Collateral Asset to receive                                         |
| `deadline`               | `uint256` | Transaction deadline                                                        |

***

## Withdraw

Burn Cork Principal Token (cPT) to exit a position pre-expiry, receiving proportional Collateral Asset and Reference Asset based on current pool composition. This is the pre-expiry counterpart to [Redeem](#redeem-post-expiry).

### safeWithdraw

Withdraw a specific amount of Collateral Asset by burning cPT.

```solidity
function safeWithdraw(SafeWithdrawParams calldata params) external
```

| Parameter             | Type      | Description                            |
| --------------------- | --------- | -------------------------------------- |
| `poolId`              | `bytes32` | MarketId                               |
| `collateralAssetsOut` | `uint256` | Amount of Collateral Asset to withdraw |
| `owner`               | `address` | Address that owns the cPT being burned |
| `receiver`            | `address` | Receives the withdrawn assets          |
| `maxCptSharesIn`      | `uint256` | Maximum cPT shares to burn             |
| `deadline`            | `uint256` | Transaction deadline                   |

### safeWithdrawOther

Withdraw a specific amount of Reference Asset by burning cPT.

```solidity
function safeWithdrawOther(SafeWithdrawOtherParams calldata params) external
```

| Parameter            | Type      | Description                            |
| -------------------- | --------- | -------------------------------------- |
| `poolId`             | `bytes32` | MarketId                               |
| `referenceAssetsOut` | `uint256` | Amount of Reference Asset to withdraw  |
| `owner`              | `address` | Address that owns the cPT being burned |
| `receiver`           | `address` | Receives the withdrawn assets          |
| `maxCptSharesIn`     | `uint256` | Maximum cPT shares to burn             |
| `deadline`           | `uint256` | Transaction deadline                   |

***

## Redeem (Post-Expiry)

Burn Cork Principal Token (cPT) after the pool has expired to receive proportional Collateral Asset and Reference Asset.

### safeRedeem

```solidity
function safeRedeem(SafeRedeemParams memory params) external
```

| Parameter                | Type      | Description                                                      |
| ------------------------ | --------- | ---------------------------------------------------------------- |
| `poolId`                 | `bytes32` | MarketId                                                         |
| `cptSharesIn`            | `uint256` | Amount of cPT to redeem. Pass `type(uint256).max` to redeem all. |
| `owner`                  | `address` | Address that owns the cPT                                        |
| `receiver`               | `address` | Receives the redeemed assets                                     |
| `minReferenceAssetsOut`  | `uint256` | Minimum Reference Asset to receive                               |
| `minCollateralAssetsOut` | `uint256` | Minimum Collateral Asset to receive                              |
| `deadline`               | `uint256` | Transaction deadline                                             |

***

## Exercise

Exercise Cork Swap Token (cST) coverage — provide Reference Asset + cST to receive Collateral Asset (minus an exercise fee). Available before expiry only.

### safeExercise

Specify the amount of cST to exercise.

```solidity
function safeExercise(SafeExerciseParams calldata params) external
```

| Parameter                | Type      | Description                         |
| ------------------------ | --------- | ----------------------------------- |
| `poolId`                 | `bytes32` | MarketId                            |
| `cstSharesIn`            | `uint256` | Amount of cST shares to exercise    |
| `receiver`               | `address` | Receives the Collateral Asset       |
| `minCollateralAssetsOut` | `uint256` | Minimum Collateral Asset to receive |
| `maxReferenceAssetsIn`   | `uint256` | Maximum Reference Asset to spend    |
| `deadline`               | `uint256` | Transaction deadline                |

### safeExerciseOther

Specify the amount of Reference Asset to provide; the required cST is computed automatically.

```solidity
function safeExerciseOther(SafeExerciseOtherParams calldata params) external
```

| Parameter                | Type      | Description                          |
| ------------------------ | --------- | ------------------------------------ |
| `poolId`                 | `bytes32` | MarketId                             |
| `referenceAssetsIn`      | `uint256` | Amount of Reference Asset to provide |
| `receiver`               | `address` | Receives the Collateral Asset        |
| `minCollateralAssetsOut` | `uint256` | Minimum Collateral Asset to receive  |
| `maxCstSharesIn`         | `uint256` | Maximum cST shares to spend          |
| `deadline`               | `uint256` | Transaction deadline                 |

### safeSwap

Specify the amount of Collateral Asset to receive; the required cST and Reference Asset are computed automatically.

```solidity
function safeSwap(SafeSwapParams calldata params) external
```

| Parameter              | Type      | Description                                 |
| ---------------------- | --------- | ------------------------------------------- |
| `poolId`               | `bytes32` | MarketId                                    |
| `collateralAssetsOut`  | `uint256` | Exact amount of Collateral Asset to receive |
| `receiver`             | `address` | Receives the Collateral Asset               |
| `maxCstSharesIn`       | `uint256` | Maximum cST shares to spend                 |
| `maxReferenceAssetsIn` | `uint256` | Maximum Reference Asset to spend            |
| `deadline`             | `uint256` | Transaction deadline                        |

***

## Repurchase (Unwind Exercise)

Reverse an exercise — provide Collateral Asset to get back Reference Asset + Cork Swap Token (cST). Available before expiry only.

### safeUnwindSwap

Specify the Collateral Asset to provide; receive Reference Asset + cST.

```solidity
function safeUnwindSwap(SafeUnwindSwapParams memory params) external
```

| Parameter               | Type      | Description                                                                          |
| ----------------------- | --------- | ------------------------------------------------------------------------------------ |
| `poolId`                | `bytes32` | MarketId                                                                             |
| `collateralAssetsIn`    | `uint256` | Amount of Collateral Asset to provide. Pass `type(uint256).max` to use full balance. |
| `receiver`              | `address` | Receives the Reference Asset and cST                                                 |
| `minReferenceAssetsOut` | `uint256` | Minimum Reference Asset to receive                                                   |
| `minCstSharesOut`       | `uint256` | Minimum cST shares to receive                                                        |
| `deadline`              | `uint256` | Transaction deadline                                                                 |

### safeUnwindExercise

Specify the cST amount to unlock; provide Collateral Asset in exchange.

```solidity
function safeUnwindExercise(SafeUnwindExerciseParams calldata params) external
```

| Parameter               | Type      | Description                        |
| ----------------------- | --------- | ---------------------------------- |
| `poolId`                | `bytes32` | MarketId                           |
| `cstSharesOut`          | `uint256` | Amount of cST shares to unlock     |
| `receiver`              | `address` | Receives cST and Reference Asset   |
| `minReferenceAssetsOut` | `uint256` | Minimum Reference Asset to receive |
| `maxCollateralAssetsIn` | `uint256` | Maximum Collateral Asset to spend  |
| `deadline`              | `uint256` | Transaction deadline               |

### safeUnwindExerciseOther

Specify the Reference Asset amount to unlock; provide Collateral Asset in exchange.

```solidity
function safeUnwindExerciseOther(SafeUnwindExerciseOtherParams calldata params) external
```

| Parameter               | Type      | Description                         |
| ----------------------- | --------- | ----------------------------------- |
| `poolId`                | `bytes32` | MarketId                            |
| `referenceAssetsOut`    | `uint256` | Amount of Reference Asset to unlock |
| `receiver`              | `address` | Receives cST and Reference Asset    |
| `minCstSharesOut`       | `uint256` | Minimum cST shares to receive       |
| `maxCollateralAssetsIn` | `uint256` | Maximum Collateral Asset to spend   |
| `deadline`              | `uint256` | Transaction deadline                |

***

## Error Reference

These errors may be thrown by CorkAdapter operations:

| Error                                                                 | Cause                                                                                                  |
| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `DeadlineExceeded()`                                                  | Transaction was mined after the specified deadline                                                     |
| `InsufficientLiquidity(uint256 available, uint256 requested)`         | The pool does not have enough Reference Asset + cST liquidity to fill the requested unwind swap amount |
| `NotWhitelisted(address account, bytes32 marketId)`                   | The caller is not on the whitelist for this market                                                     |
| `Expired()`                                                           | Attempted a pre-expiry operation on an expired pool                                                    |
| `NotExpired()`                                                        | Attempted a post-expiry operation (redeem) on a pool that has not expired                              |
| `ZeroAmount()`                                                        | Input amount is zero                                                                                   |
| `InsufficientSharesAmount(uint256 minimumRequired, uint256 provided)` | Slippage check failed — output is less than the specified minimum                                      |
| `InsufficientAmount()`                                                | Input amount does not meet the minimum requirements                                                    |


# CorkPoolManager

Singleton pool manager — all pool state, queries, previews, and raw operations

**Address:** `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC` (same on all chains)

CorkPoolManager is the singleton contract that holds all Cork Pool state and executes all pool operations. Use it directly for read operations. For write operations, use [CorkAdapter](/developers/contract-reference/cork-adapter) which adds slippage and deadline protection.

## Query Functions

These are the primary read functions for integrators.

### swapRate

```solidity
function swapRate(MarketId poolId) external view returns (uint256 rate)
```

Returns the exchange rate between Reference Asset and Collateral Asset, scaled to 18 decimals.

**Interpretation:** 1 Reference Asset = `rate / 1e18` Collateral Assets.

Example: a rate of `0.82e18` (820000000000000000) means 1 Reference Asset is worth 0.82 Collateral Assets.

```typescript
const rate = await client.readContract({
  address: CORK_POOL_MANAGER,
  abi: poolManagerAbi,
  functionName: 'swapRate',
  args: [MARKET_ID],
})
// rate = 820000000000000000n → 1 REF = 0.82 CA
```

### assets

```solidity
function assets(MarketId poolId) external view returns (uint256 collateralAssets, uint256 referenceAssets)
```

Returns the pool's Collateral Asset and Reference Asset balances in their native token decimals.

```typescript
const [collateral, reference] = await client.readContract({
  address: CORK_POOL_MANAGER,
  abi: poolManagerAbi,
  functionName: 'assets',
  args: [MARKET_ID],
})
```

### shares

```solidity
function shares(MarketId poolId) external view returns (address principalToken, address swapToken)
```

Returns the Cork Principal Token (cPT) and Cork Swap Token (cST) contract addresses for a given market.

### market

```solidity
function market(MarketId poolId) external view returns (Market memory)
```

Returns the full Market configuration struct (all 8 fields). See [Key Concepts](#key-concepts) below.

### getId

```solidity
function getId(Market calldata marketParameters) external view returns (MarketId marketId)
```

Computes a MarketId from a Market struct. Useful for on-chain MarketId derivation.

***

## Preview Functions

Preview functions return the expected output of an operation without executing it. Use them for UI quotes, pre-flight checks, and computing slippage parameters for CorkAdapter.

{% hint style="info" %}
Preview functions return `0` (or all zeros for multi-value returns) if the operation is currently paused or if the pool has expired (for pre-expiry operations).
{% endhint %}

### Deposit Previews

```solidity
function previewDeposit(MarketId poolId, uint256 collateralAssetsIn)
    external view returns (uint256 cptAndCstSharesOut)

function previewMint(MarketId poolId, uint256 cptAndCstSharesOut)
    external view returns (uint256 collateralAssetsIn)
```

### Unwind Deposit Previews

```solidity
function previewUnwindDeposit(MarketId poolId, uint256 collateralAssetsOut)
    external view returns (uint256 cptAndCstSharesIn)

function previewUnwindMint(MarketId poolId, uint256 cptAndCstSharesIn)
    external view returns (uint256 collateralAssetsOut)
```

### Withdraw Previews

```solidity
function previewWithdraw(MarketId poolId, uint256 collateralAssetsOut)
    external view returns (uint256 cptSharesIn, uint256 actualCollateralAssetsOut, uint256 actualReferenceAssetsOut)

function previewWithdrawOther(MarketId poolId, uint256 referenceAssetsOut)
    external view returns (uint256 cptSharesIn, uint256 actualCollateralAssetsOut, uint256 actualReferenceAssetsOut)
```

### Redeem Preview

```solidity
function previewRedeem(MarketId poolId, uint256 cptSharesIn)
    external view returns (uint256 referenceAssetsOut, uint256 collateralAssetsOut)
```

### Exercise Previews

```solidity
function previewExercise(MarketId poolId, uint256 cstSharesIn)
    external view returns (uint256 collateralAssetsOut, uint256 referenceAssetsIn, uint256 fee)

function previewExerciseOther(MarketId poolId, uint256 referenceAssetsIn)
    external view returns (uint256 collateralAssetsOut, uint256 cstSharesIn, uint256 fee)

function previewSwap(MarketId poolId, uint256 collateralAssetsOut)
    external view returns (uint256 cstSharesIn, uint256 referenceAssetsIn, uint256 fee)
```

### Unwind Exercise / Swap Previews

```solidity
function previewUnwindSwap(MarketId poolId, uint256 collateralAssetsIn)
    external view returns (uint256 cstSharesOut, uint256 referenceAssetsOut, uint256 fee)

function previewUnwindExercise(MarketId poolId, uint256 cstSharesOut)
    external view returns (uint256 collateralAssetsIn, uint256 referenceAssetsOut, uint256 fee)

function previewUnwindExerciseOther(MarketId poolId, uint256 referenceAssetsOut)
    external view returns (uint256 collateralAssetsIn, uint256 cstSharesOut, uint256 fee)
```

***

## Max Functions

Returns the maximum amount the given address can use for each operation. Accounts for token balances, allowances, and pool liquidity.

```solidity
// Deposit
function maxDeposit(MarketId poolId, address owner) external view returns (uint256)
function maxMint(MarketId poolId, address owner) external view returns (uint256)

// Unwind Deposit
function maxUnwindDeposit(MarketId poolId, address owner) external view returns (uint256)
function maxUnwindMint(MarketId poolId, address owner) external view returns (uint256)

// Withdraw
function maxWithdraw(MarketId poolId, address owner) external view returns (uint256)
function maxWithdrawOther(MarketId poolId, address owner) external view returns (uint256)

// Redeem
function maxRedeem(MarketId poolId, address owner) external view returns (uint256)

// Exercise / Swap
function maxExercise(MarketId poolId, address owner) external view returns (uint256)
function maxExerciseOther(MarketId poolId, address owner) external view returns (uint256)
function maxSwap(MarketId poolId, address owner) external view returns (uint256)

// Unwind Exercise / Swap
function maxUnwindSwap(MarketId poolId, address) external view returns (uint256)
function maxUnwindExercise(MarketId poolId, address) external view returns (uint256)
function maxUnwindExerciseOther(MarketId poolId, address) external view returns (uint256)
```

***

## Fee Functions

```solidity
function swapFee(MarketId poolId) external view returns (uint256 fees)
function unwindSwapFee(MarketId poolId) external view returns (uint256 fees)
```

Fees use 18-decimal precision: `1e18 = 1%`. The maximum allowed fee is `5e18` (5%). Fees apply to exercise/swap and unwind exercise/swap operations.

***

## Raw Operation Functions

CorkPoolManager exposes all pool operations directly. These functions execute the operation without slippage or deadline checks.

{% hint style="warning" %}
These functions lack slippage and deadline protection. For production integrations, use [CorkAdapter](/developers/contract-reference/cork-adapter) safe wrappers instead.
{% endhint %}

```solidity
// Deposit
function deposit(MarketId poolId, uint256 collateralAssetsIn, address receiver)
    external returns (uint256 cptAndCstSharesOut)
function mint(MarketId poolId, uint256 cptAndCstSharesOut, address receiver)
    external returns (uint256 collateralAssetsIn)

// Unwind Deposit
function unwindDeposit(MarketId poolId, uint256 collateralAssetsOut, address owner, address receiver)
    external returns (uint256 cptAndCstSharesIn)
function unwindMint(MarketId poolId, uint256 cptAndCstSharesIn, address owner, address receiver)
    external returns (uint256 collateralAssetsOut)

// Withdraw
function withdraw(MarketId poolId, uint256 collateralAssetsOut, address owner, address receiver)
    external returns (uint256 cptSharesIn, uint256 actualCollateralAssetsOut, uint256 actualReferenceAssetsOut)
function withdrawOther(MarketId poolId, uint256 referenceAssetsOut, address owner, address receiver)
    external returns (uint256 cptSharesIn, uint256 actualCollateralAssetsOut, uint256 actualReferenceAssetsOut)

// Redeem (post-expiry)
function redeem(MarketId poolId, uint256 cptSharesIn, address owner, address receiver)
    external returns (uint256 referenceAssetsOut, uint256 collateralAssetsOut)

// Exercise / Swap
function exercise(MarketId poolId, uint256 cstSharesIn, address receiver)
    external returns (uint256 collateralAssetsOut, uint256 referenceAssetsIn, uint256 fee)
function exerciseOther(MarketId poolId, uint256 referenceAssetsIn, address receiver)
    external returns (uint256 collateralAssetsOut, uint256 cstSharesIn, uint256 fee)
function swap(MarketId poolId, uint256 collateralAssetsOut, address receiver)
    external returns (uint256 cstSharesIn, uint256 referenceAssetsIn, uint256 fee)

// Unwind Exercise / Swap
function unwindSwap(MarketId poolId, uint256 collateralAssetsIn, address receiver)
    external returns (uint256 cstSharesOut, uint256 referenceAssetsOut, uint256 fee)
function unwindExercise(MarketId poolId, uint256 cstSharesOut, address receiver)
    external returns (uint256 collateralAssetsIn, uint256 referenceAssetsOut, uint256 fee)
function unwindExerciseOther(MarketId poolId, uint256 referenceAssetsOut, address receiver)
    external returns (uint256 collateralAssetsIn, uint256 cstSharesOut, uint256 fee)
```

***

## Key Concepts

### Market Struct

Every Cork Pool is defined by a Market struct containing 8 fields:

| Field                   | Type      | Description                                                                                                                      |
| ----------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `collateralAsset`       | `address` | The yield-bearing asset deposited into the pool (e.g., sUSDe)                                                                    |
| `referenceAsset`        | `address` | The asset whose risk is being hedged (e.g., vbUSDC)                                                                              |
| `expiryTimestamp`       | `uint256` | Unix timestamp when the pool expires                                                                                             |
| `rateMin`               | `uint256` | Minimum swap rate the oracle can return (18 decimals). Rates below this are clamped.                                             |
| `rateMax`               | `uint256` | Maximum swap rate the oracle can return (18 decimals). Rates above this are clamped.                                             |
| `rateChangePerDayMax`   | `uint256` | Maximum allowed rate change per day in absolute value (18 decimals)                                                              |
| `rateChangeCapacityMax` | `uint256` | Maximum accumulated rate change capacity (18 decimals). Caps how much rate can change even if `rateChangePerDayMax` allows more. |
| `rateOracle`            | `address` | Oracle contract providing the rate between Reference Asset and Collateral Asset                                                  |

### MarketId Computation

A MarketId is the `keccak256` hash of the ABI-encoded Market struct:

```solidity
MarketId marketId = MarketId.wrap(keccak256(abi.encode(market)));
```

In TypeScript with viem:

```typescript
import { encodeAbiParameters, keccak256 } from 'viem'

const marketId = keccak256(
  encodeAbiParameters(
    [
      { type: 'address' }, // collateralAsset
      { type: 'address' }, // referenceAsset
      { type: 'uint256' }, // expiryTimestamp
      { type: 'uint256' }, // rateMin
      { type: 'uint256' }, // rateMax
      { type: 'uint256' }, // rateChangePerDayMax
      { type: 'uint256' }, // rateChangeCapacityMax
      { type: 'address' }, // rateOracle
    ],
    [
      collateralAsset,
      referenceAsset,
      expiryTimestamp,
      rateMin,
      rateMax,
      rateChangePerDayMax,
      rateChangeCapacityMax,
      rateOracle,
    ]
  )
)
```

You can also compute it on-chain by calling `getId(Market)` on CorkPoolManager.

{% hint style="info" %}
A MarketId is deterministic — the same Market parameters always produce the same MarketId, regardless of which chain you compute it on.
{% endhint %}

### Operations Table

#### Before Expiry

| Operation                                    | You Provide      | You Receive             | Pool Effect        |
| -------------------------------------------- | ---------------- | ----------------------- | ------------------ |
| Deposit / Mint                               | Collateral Asset | cPT + cST               | CA ↑               |
| Unwind Deposit                               | cPT + cST        | Collateral Asset        | CA ↓               |
| Withdraw                                     | cPT              | CA + REF (proportional) | CA ↓, REF ↓        |
| Exercise (`swap` / `exercise`)               | REF + cST        | Collateral Asset - Fee  | CA ↓, REF ↑, cST ↑ |
| Repurchase (`unwindSwap` / `unwindExercise`) | Collateral Asset | REF + cST               | CA ↑, REF ↓, cST ↓ |

#### After Expiry

| Operation | You Provide | You Receive                                 |
| --------- | ----------- | ------------------------------------------- |
| Redeem    | cPT         | CA + REF (proportional to pool composition) |

### Swap Rate Formula

The swap rate determines how much Collateral Asset you receive per Reference Asset when exercising:

```
collateralOut = referenceIn × swapRate / 1e18
```

Example: with `swapRate = 0.82e18`, exercising with 100 REF returns 82 CA (before fees). The exercise also consumes cST — see [previewExercise](#exercise-previews) for exact amounts.

### Decimal Normalization

All Cork Principal Token (cPT) and Cork Swap Token (cST) amounts use **18 decimals**, regardless of the underlying token's decimals. When the Collateral Asset or Reference Asset has different decimals (e.g., USDC with 6 decimals), the protocol normalizes internally.

* **Input amounts** to contract functions should be in the token's **native decimals** (e.g., 6 decimals for USDC-based assets)
* **Share amounts** (cPT, cST) are always **18 decimals**
* **Swap rates and fees** are always **18 decimals**

### Pause Bitmap

Each pool has a 5-bit pause bitmap controlling which operations are active:

| Bit | Operation                    |
| --- | ---------------------------- |
| 0   | Deposit                      |
| 1   | Swap / Exercise              |
| 2   | Withdrawal                   |
| 3   | Unwind Deposit / Unwind Mint |
| 4   | Unwind Swap / Exercise       |

Query the pause state via `getPausedBitMap(MarketId)` or use the DefaultCorkController convenience functions (`isDepositPaused`, `isSwapPaused`, etc.) documented in [Admin & Governance](/developers/contract-reference/admin-and-governance).


# Admin & Governance

Governance, access control, rate protection, and token factory contracts

These contracts handle protocol governance, access control, and infrastructure. They are primarily relevant to protocol operators rather than integrators.

***

## DefaultCorkController

**Address:** `0xcCcCcCccCccbC06627F8aad7aAF13fe3a457f779`

Governance contract that manages pool creation, fee configuration, pause control, and whitelist management. Only accounts with the appropriate roles can call these functions.

### Pool Creation

```solidity
struct PoolCreationParams {
    Market pool;
    uint256 unwindSwapFeePercentage; // 18 decimals, 1e18 = 1%
    uint256 swapFeePercentage;       // 18 decimals, 1e18 = 1%
    bool isWhitelistEnabled;
}

function createNewPool(PoolCreationParams calldata params) external
```

### Fee Management

```solidity
function updateSwapFeePercentage(MarketId id, uint256 newSwapFeePercentage) external
function updateUnwindSwapFeePercentage(MarketId id, uint256 newUnwindSwapFeePercentage) external
```

Fees use 18-decimal precision (`1e18 = 1%`). Maximum allowed fee is `5e18` (5%).

### Pause Control

Per-market pause functions:

```solidity
function pauseDeposits(MarketId id) external
function unpauseDeposits(MarketId id) external
function pauseSwaps(MarketId id) external
function unpauseSwaps(MarketId id) external
function pauseWithdrawals(MarketId id) external
function unpauseWithdrawals(MarketId id) external
function pauseUnwindDepositAndMints(MarketId id) external
function unpauseUnwindDepositAndMints(MarketId id) external
function pauseUnwindSwaps(MarketId id) external
function unpauseUnwindSwaps(MarketId id) external
function pauseMarket(MarketId id) external  // pauses all operations
```

Single-market emergency pause/unpause:

```solidity
function pause(MarketId id) external
function unpause(MarketId id) external
```

All-markets pause:

```solidity
function pauseAll() external
function unpauseAll() external
```

### Pause Queries

```solidity
function isDepositPaused(MarketId id) external view returns (bool)
function isSwapPaused(MarketId id) external view returns (bool)
function isWithdrawalPaused(MarketId id) external view returns (bool)
function isUnwindDepositAndMintPaused(MarketId id) external view returns (bool)
function isUnwindSwapPaused(MarketId id) external view returns (bool)
```

### Whitelist Management

```solidity
function disableMarketWhitelist(MarketId marketId) external
function addToGlobalWhitelist(address[] calldata accounts) external
function removeFromGlobalWhitelist(address[] calldata accounts) external
function addToMarketWhitelist(MarketId marketId, address[] calldata accounts) external
function removeFromMarketWhitelist(MarketId marketId, address[] calldata accounts) external
function isWhitelisted(MarketId marketId, address account) external view returns (bool)
```

***

## WhitelistManager

**Address:** `0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE`

Manages global and per-market access control. An address is considered whitelisted if it is on the global whitelist OR the specific market whitelist.

```solidity
function isMarketWhitelistEnabled(MarketId poolId) external view returns (bool)
function isGlobalWhitelisted(address account) external view returns (bool)
function isMarketWhitelisted(MarketId poolId, address account) external view returns (bool)
function isWhitelisted(MarketId poolId, address account) external view returns (bool)
```

{% hint style="info" %}
`isWhitelisted` is the combined check — returns `true` if the market's whitelist is disabled (all addresses pass) OR if the account is on the global or market-specific whitelist. Use this for pre-flight checks before deposits.
{% endhint %}

***

## ConstraintRateAdapter

**Address:** `0xCCcCcCcccCccEF378949D1a61ED2283C831AF03A`

Protects against oracle manipulation by constraining how much the swap rate can change per day and in total. Wraps the rate oracle and applies daily change limits and capacity caps defined in the Market struct.

```solidity
function adjustedRate(MarketId poolId) external returns (uint256 rate)
function previewAdjustedRate(MarketId poolId) external view returns (uint256 rate)
function constraints(MarketId poolId) external view returns (
    uint256, // lastAdjustedRate
    uint256, // lastAdjustmentTimestamp
    uint256  // remainingCredits
)
```

* `adjustedRate` — fetches the oracle rate, applies constraints, and saves the new state. **Non-view**: this writes constraint state on-chain. Use `previewAdjustedRate` for read-only access
* `previewAdjustedRate` — same computation without writing state (view function)
* `constraints` — returns the current constraint state for a market

***

## SharesFactory

**Address:** `0xcCCCccCCCcCc1782617fe14A386AC910a20D4324`

Deploys paired Cork Principal Token (cPT) and Cork Swap Token (cST) contracts when a new pool is created.

```solidity
struct DeployParams {
    Market poolParams;
    MarketId poolId;
}

function deployPoolShares(DeployParams calldata params)
    external returns (address principalToken, address swapToken)
```

***

## PoolShare Tokens (cPT / cST)

Each Cork Pool issues two ERC20 tokens. Both implement standard ERC20 with EIP-2612 Permit support.

### Standard ERC20

`transfer`, `approve`, `balanceOf`, `totalSupply`, `allowance`, `permit` — standard interfaces.

### Pool-Specific Queries

```solidity
function poolId() external view returns (MarketId)
function poolManager() external view returns (IPoolManager)
function factory() external view returns (address)
function isExpired() external view returns (bool)
function expiry() external view returns (uint256)
function issuedAt() external view returns (uint256)
function pairName() external view returns (string memory)
function getReserves() external view returns (uint256 collateralAssets, uint256 referenceAssets)
```

### Convenience Functions

PoolShare tokens also expose all `preview*` and `max*` functions from CorkPoolManager as convenience wrappers, allowing you to query pool state directly from the token contract without needing to know the CorkPoolManager address.


# API Reference

Cork Protocol REST API for market discovery, transaction history, and limit orders

**Base URL:** `https://api-phoenix.cork.tech`\
**Interactive docs:** <https://api-phoenix.cork.tech/docs>

Use on-chain reads (CorkPoolManager) for real-time state like swap rates and pool balances. Use this API for historical data, market discovery, and limit order management.

{% hint style="info" %}
Always include `chainId=1` in queries to filter to Ethereum mainnet. Other chain IDs may return testnet data.
{% endhint %}

## Pagination

All list endpoints return paginated responses with this structure:

```json
{
  "items": [...],
  "nextCursor": "abc123",
  "hasMore": true
}
```

Pass `nextCursor` as a query parameter to fetch the next page. When `hasMore` is `false`, you have reached the end of the results.

***

## Pools

### List Pools

```
GET /v1/pools/
```

Returns pool metadata, TVL, fee configuration, and pause status.

**Parameters:**

| Parameter             | Type     | Description                                          |
| --------------------- | -------- | ---------------------------------------------------- |
| `chainId`             | `number` | Chain ID (use `1` for mainnet)                       |
| `poolId`              | `string` | Filter by specific MarketId                          |
| `collateralAddress`   | `string` | Filter by Collateral Asset address                   |
| `referenceAddress`    | `string` | Filter by Reference Asset address                    |
| `principalAddress`    | `string` | Filter by cPT token address                          |
| `swapAddress`         | `string` | Filter by cST token address                          |
| `poolWhitelistStatus` | `string` | Filter by whitelist enabled/disabled                 |
| `expiryBefore`        | `string` | ISO 8601 timestamp — pools expiring before this date |
| `expiryAfter`         | `string` | ISO 8601 timestamp — pools expiring after this date  |
| `limit`               | `number` | Results per page (default: 2000, max: 2000)          |
| `nextCursor`          | `string` | Pagination cursor                                    |

**Example:**

```bash
curl "https://api-phoenix.cork.tech/v1/pools/?chainId=1"
```

**Response shape:**

```json
{
  "items": [
    {
      "chainId": 1,
      "poolId": "0xab4988fb673606b689a98dc06bdb3799c88a1300b6811421cd710aa8f86b702a",
      "poolName": "sUSDe-vbUSDC-20APR2026",
      "expiry": "2026-04-20T00:00:00.000Z",
      "collateralToken": {
        "address": "0x9D39A5DE30e57443BfF2A8307A4256c8797A3497",
        "name": "Staked USDe",
        "symbol": "sUSDe",
        "decimals": 18
      },
      "referenceToken": {
        "address": "0x53E82ABbb12638F09d9e624578ccB666217a765e",
        "name": "Vault Batching USDC",
        "symbol": "vbUSDC",
        "decimals": 6
      },
      "principalToken": {
        "address": "0x...",
        "name": "Cork Principal Token ...",
        "symbol": "cPT-...",
        "decimals": 18
      },
      "swapToken": {
        "address": "0x...",
        "name": "Cork Swap Token ...",
        "symbol": "cST-...",
        "decimals": 18
      },
      "isWhitelistEnabled": true,
      "isDepositPaused": false,
      "isWithdrawPaused": false,
      "isSwapPaused": false,
      "isUnwindSwapPaused": false,
      "isUnwindDepositPaused": false,
      "exerciseFeePercentage": 0.01,
      "repurchaseFeePercentage": 0.01,
      "tvl": {
        "inUsdAtNow": 1234567.89,
        "inUsdAtEvents": 1200000.00
      },
      "collateralValue": {
        "inWei": "1000500000000000000000",
        "inToken": 1000.5,
        "inUsdAtNow": 1000.5,
        "inUsdAtEvents": 980.0
      },
      "referenceValue": {
        "inWei": "500000000",
        "inToken": 500.0,
        "inUsdAtNow": 500.0,
        "inUsdAtEvents": 490.0
      }
    }
  ],
  "nextCursor": null,
  "hasMore": false
}
```

**Key response fields:**

* `tvl.inUsdAtNow` — current USD value of all pool assets
* `collateralValue` / `referenceValue` — asset balances in wei, token units, and USD
* `inUsdAtNow` — current USD valuation
* `inUsdAtEvents` — USD valuation at the time of the last on-chain event
* `exerciseFeePercentage` / `repurchaseFeePercentage` — decimal fractions (0.01 = 1%). On-chain, fees use 18-decimal precision (`1e18 = 1%`) — see [CorkPoolManager > Fee Functions](/developers/contract-reference/cork-pool-manager#fee-functions)

### Whitelisted Addresses

```
GET /v1/pools/whitelisted-addresses
```

Returns pools with their whitelisted addresses.

**Parameters:**

| Parameter             | Type     | Description                                 |
| --------------------- | -------- | ------------------------------------------- |
| `chainId`             | `number` | Chain ID                                    |
| `poolId`              | `string` | Filter by specific MarketId                 |
| `walletAddress`       | `string` | Check if a specific address is whitelisted  |
| `poolWhitelistStatus` | `string` | Filter by whitelist enabled/disabled        |
| `limit`               | `number` | Results per page (default: 2000, max: 2000) |
| `nextCursor`          | `string` | Pagination cursor                           |

**Response shape:**

```json
{
  "items": [
    {
      "chainId": 1,
      "poolId": "0x...",
      "poolName": "sUSDe-vbUSDC-20APR2026",
      "isWhitelistEnabled": true,
      "whitelistedAddresses": [
        {
          "account": "0x49903609b8a22e1d9f7406d1306191e28c8ececd",
          "isGlobalWhitelisted": false,
          "isMarketWhitelisted": true
        }
      ]
    }
  ],
  "nextCursor": null,
  "hasMore": false
}
```

***

## Flows (Transaction History)

### List Flows

```
GET /v1/flows/
```

Returns user transaction history across Cork Pool operations.

**Parameters:**

| Parameter       | Type     | Description                                                                    |
| --------------- | -------- | ------------------------------------------------------------------------------ |
| `chainId`       | `number` | Chain ID                                                                       |
| `walletAddress` | `string` | Filter by user address                                                         |
| `poolId`        | `string` | Filter by specific MarketId                                                    |
| `actionType`    | `string` | Filter by operation type: `exercise`, `repurchase`, `redeem`, `mint`, `unwind` |
| `fromTimestamp` | `string` | ISO 8601 — transactions after this time                                        |
| `toTimestamp`   | `string` | ISO 8601 — transactions before this time                                       |
| `fromBlock`     | `number` | Filter by start block                                                          |
| `toBlock`       | `number` | Filter by end block                                                            |
| `limit`         | `number` | Results per page (default: 2000, max: 2000)                                    |
| `nextCursor`    | `string` | Pagination cursor                                                              |

{% hint style="info" %}
Provide at least `walletAddress` or `poolId` to narrow results.
{% endhint %}

***

## Limit Orders

### List Markets

```
GET /v1/limit-orders/markets
```

Returns available limit order markets.

| Parameter    | Type      | Description                                |
| ------------ | --------- | ------------------------------------------ |
| `chainId`    | `number`  | Chain ID                                   |
| `poolId`     | `string`  | Filter by specific MarketId                |
| `onlyActive` | `boolean` | Only return active markets                 |
| `limit`      | `number`  | Results per page (default: 100, max: 2000) |
| `nextCursor` | `string`  | Pagination cursor                          |

### Get Orderbook

```
GET /v1/limit-orders/orderbook
```

Returns active limit orders.

| Parameter    | Type       | Description                                |
| ------------ | ---------- | ------------------------------------------ |
| `chainId`    | `number`   | Chain ID                                   |
| `poolId`     | `string`   | Filter by MarketId                         |
| `maker`      | `string`   | Filter by maker address                    |
| `side`       | `string`   | `BUY` or `SELL`                            |
| `status`     | `string[]` | Order status filter                        |
| `limit`      | `number`   | Results per page (default: 100, max: 2000) |
| `nextCursor` | `string`   | Pagination cursor                          |

### Get Fills

```
GET /v1/limit-orders/fills
```

Returns filled order history.

| Parameter       | Type     | Description                                |
| --------------- | -------- | ------------------------------------------ |
| `chainId`       | `number` | Chain ID                                   |
| `orderHash`     | `string` | Filter by specific order                   |
| `maker`         | `string` | Filter by maker address                    |
| `taker`         | `string` | Filter by taker address                    |
| `fromTimestamp` | `string` | ISO 8601 — fills after this time           |
| `toTimestamp`   | `string` | ISO 8601 — fills before this time          |
| `limit`         | `number` | Results per page (default: 100, max: 2000) |
| `nextCursor`    | `string` | Pagination cursor                          |

### Submit Order

```
POST /v1/limit-orders/
```

Submit a new limit order. Orders use EIP-712 typed signing. The `makerTraits` field encodes order constraints (expiry, partial fill settings).

{% hint style="info" %}
Limit order integration requires constructing and signing EIP-712 typed data. Contact the Cork team for the signing SDK and integration guide.
{% endhint %}

**Request body:**

| Field          | Type     | Description                              |
| -------------- | -------- | ---------------------------------------- |
| `chainId`      | `number` | Chain ID                                 |
| `salt`         | `string` | Unique order salt                        |
| `maker`        | `string` | Maker address                            |
| `receiver`     | `string` | Receiver address                         |
| `makerAsset`   | `string` | Token address the maker is selling       |
| `takerAsset`   | `string` | Token address the maker wants to receive |
| `makingAmount` | `string` | Amount of makerAsset                     |
| `takingAmount` | `string` | Amount of takerAsset                     |
| `makerTraits`  | `string` | Encoded maker traits                     |
| `orderHash`    | `string` | Hash of the order                        |
| `signature`    | `string` | EIP-712 signature                        |
| `side`         | `string` | `BUY` or `SELL`                          |
| `premium`      | `string` | Order premium                            |
| `nonce`        | `string` | Order nonce                              |


# AI Context

Structured protocol reference optimized for AI assistants and LLM consumption

This page provides a consolidated, structured reference for AI assistants integrating with or answering questions about Cork Protocol. It complements the detailed pages in this documentation by bringing together contract addresses, key function signatures, operations, and common gotchas in one place.

***

## What is Cork?

Cork is a programmable risk layer for onchain assets such as RWAs, vault tokens, and yield-bearing stablecoins. Cork's risk infrastructure primitive enables asset managers and issuers to spin up custom swap markets that enhance redemption liquidity, risk transparency, and market confidence for their onchain assets.

Each Cork Pool is built around a Collateral Asset (CA) and Reference Asset (REF) pair. Depositors provide CA and receive two tokens: Cork Principal Token (cPT) representing principal claims, and Cork Swap Token (cST) representing swap/exercise rights. cST holders can exercise coverage by exchanging REF + cST for CA — guaranteeing redemption liquidity regardless of market conditions.

All pools are managed by a single CorkPoolManager contract (singleton architecture). For write operations with slippage and deadline protection, use CorkAdapter. For read operations, query CorkPoolManager directly.

***

## Core Concepts

* **Cork Pool**: A singleton-managed pool holding Collateral Asset, issuing cPT + cST on deposit. Each pool is identified by a MarketId.
* **Cork Principal Token (cPT)**: ERC20 token representing a depositor's principal claim. Redeemable for proportional CA + REF after expiry.
* **Cork Swap Token (cST)**: ERC20 token granting the right to exercise — exchange REF + cST for CA (minus a fee) before expiry.
* **Collateral Asset (CA)**: The yield-bearing asset deposited into the pool (e.g., sUSDe, wstETH).
* **Reference Asset (REF)**: The asset whose risk is being covered (e.g., vbUSDC, ezETH).
* **Market struct**: 8 fields defining a pool — collateralAsset, referenceAsset, expiryTimestamp, rateMin, rateMax, rateChangePerDayMax, rateChangeCapacityMax, rateOracle.
* **MarketId**: `keccak256(abi.encode(Market))` — deterministic hash of all 8 Market fields. Same parameters always produce the same MarketId on any chain.
* **Swap Rate**: Exchange rate between REF and CA, scaled to 18 decimals. `collateralOut = referenceIn * swapRate / 1e18`.

***

## Contract Addresses

All addresses are identical across Ethereum mainnet and supported chains (deterministic CREATE2 deployment).

| Contract              | Address                                      | Purpose                                         |
| --------------------- | -------------------------------------------- | ----------------------------------------------- |
| CorkPoolManager       | `0xccCCcCcCCccCfAE2Ee43F0E727A8c2969d74B9eC` | Singleton — all pool state and operations       |
| CorkAdapter           | `0xCCcCcCCCcccCBaD6F772a511B337d9CCc9570407` | Safe wrappers with slippage/deadline protection |
| DefaultCorkController | `0xcCcCcCccCccbC06627F8aad7aAF13fe3a457f779` | Governance: pool creation, fees, pause control  |
| WhitelistManager      | `0xcCccCcCccCC6e38a2772Eb42D2f408eeB89cb0eE` | Global and per-market access control            |
| ConstraintRateAdapter | `0xCCcCcCcccCccEF378949D1a61ED2283C831AF03A` | Oracle rate protection with daily change limits |
| SharesFactory         | `0xcCCCccCCCcCc1782617fe14A386AC910a20D4324` | cPT/cST token pair deployment                   |

***

## Key Functions

### Read Operations (call CorkPoolManager)

```solidity
// Pool state
function swapRate(MarketId poolId) external view returns (uint256 rate)
function assets(MarketId poolId) external view returns (uint256 collateralAssets, uint256 referenceAssets)
function shares(MarketId poolId) external view returns (address principalToken, address swapToken)
function market(MarketId poolId) external view returns (Market memory)

// Preview operations (returns expected output without executing)
function previewDeposit(MarketId poolId, uint256 collateralAssetsIn) external view returns (uint256 cptAndCstSharesOut)
function previewExercise(MarketId poolId, uint256 cstSharesIn) external view returns (uint256 collateralAssetsOut, uint256 referenceAssetsIn, uint256 fee)
function previewRedeem(MarketId poolId, uint256 cptSharesIn) external view returns (uint256 referenceAssetsOut, uint256 collateralAssetsOut)
function previewUnwindDeposit(MarketId poolId, uint256 collateralAssetsOut) external view returns (uint256 cptAndCstSharesIn)
function previewUnwindSwap(MarketId poolId, uint256 collateralAssetsIn) external view returns (uint256 cstSharesOut, uint256 referenceAssetsOut, uint256 fee)
function previewWithdraw(MarketId poolId, uint256 collateralAssetsOut) external view returns (uint256 cptSharesIn, uint256 actualCollateralAssetsOut, uint256 actualReferenceAssetsOut)

// Max amounts (accounts for balances, allowances, pool liquidity)
function maxDeposit(MarketId poolId, address owner) external view returns (uint256)
function maxExercise(MarketId poolId, address owner) external view returns (uint256)
function maxRedeem(MarketId poolId, address owner) external view returns (uint256)

// Fees (18-decimal precision: 1e18 = 1%, max 5e18 = 5%)
function swapFee(MarketId poolId) external view returns (uint256 fees)
function unwindSwapFee(MarketId poolId) external view returns (uint256 fees)

// Whitelist check (call WhitelistManager)
function isWhitelisted(MarketId marketId, address account) external view returns (bool)
```

### Write Operations (call CorkAdapter for production use)

```solidity
// Deposit: CA → cPT + cST
function safeDeposit(SafeDepositParams calldata params) external
// params: poolId, collateralAssetsIn, receiver, minCptAndCstSharesOut, deadline

// Exercise: REF + cST → CA (minus fee) — before expiry
function safeExercise(SafeExerciseParams calldata params) external
// params: poolId, cstSharesIn, receiver, minCollateralAssetsOut, maxReferenceAssetsIn, deadline

function safeSwap(SafeSwapParams calldata params) external
// params: poolId, collateralAssetsOut, receiver, maxCstSharesIn, maxReferenceAssetsIn, deadline

// Withdraw: cPT → CA + REF (proportional) — before expiry
function safeWithdraw(SafeWithdrawParams calldata params) external
// params: poolId, collateralAssetsOut, owner, receiver, maxCptSharesIn, deadline

// Redeem: cPT → CA + REF (proportional) — after expiry
function safeRedeem(SafeRedeemParams memory params) external
// params: poolId, cptSharesIn, owner, receiver, minReferenceAssetsOut, minCollateralAssetsOut, deadline

// Unwind Deposit: cPT + cST → CA — before expiry
function safeUnwindDeposit(SafeUnwindDepositParams calldata params) external
// params: poolId, collateralAssetsOut, owner, receiver, maxCptAndCstSharesIn, deadline

// Repurchase: CA → REF + cST — before expiry
function safeUnwindSwap(SafeUnwindSwapParams memory params) external
// params: poolId, collateralAssetsIn, receiver, minReferenceAssetsOut, minCstSharesOut, deadline
```

### MarketId Computation

```solidity
// Solidity
MarketId marketId = MarketId.wrap(keccak256(abi.encode(market)));

// TypeScript (viem)
import { encodeAbiParameters, keccak256 } from 'viem'
const marketId = keccak256(encodeAbiParameters(
  [{ type: 'address' }, { type: 'address' }, { type: 'uint256' },
   { type: 'uint256' }, { type: 'uint256' }, { type: 'uint256' },
   { type: 'uint256' }, { type: 'address' }],
  [collateralAsset, referenceAsset, expiryTimestamp,
   rateMin, rateMax, rateChangePerDayMax, rateChangeCapacityMax, rateOracle]
))
```

***

## Operations Summary

### Before Expiry

| Operation      | You Provide      | You Receive                  |
| -------------- | ---------------- | ---------------------------- |
| Deposit        | Collateral Asset | cPT + cST                    |
| Unwind Deposit | cPT + cST        | Collateral Asset             |
| Withdraw       | cPT              | CA + REF (proportional)      |
| Exercise       | REF + cST        | Collateral Asset (minus fee) |
| Repurchase     | Collateral Asset | REF + cST                    |

### After Expiry

| Operation | You Provide | You Receive                                 |
| --------- | ----------- | ------------------------------------------- |
| Redeem    | cPT         | CA + REF (proportional to pool composition) |

***

## API

* **Base URL**: `https://api-phoenix.cork.tech`
* **Interactive docs**: <https://api-phoenix.cork.tech/docs>
* **Key endpoints**:
  * `GET /v1/pools/?chainId=1` — list pools with TVL, fees, pause status
  * `GET /v1/pools/whitelisted-addresses?chainId=1` — check whitelist status
  * `GET /v1/flows/?chainId=1` — transaction history
  * `GET /v1/limit-orders/markets?chainId=1` — limit order markets
* Always include `chainId=1` for Ethereum mainnet

***

## Key Gotchas

* **18-decimal shares**: cPT and cST always use 18 decimals, regardless of the underlying token's decimals (e.g., 6-decimal USDC produces 18-decimal cPT/cST)
* **Fees**: 18-decimal precision where `1e18 = 1%`. Maximum fee is `5e18` (5%). Fees apply to Exercise and Repurchase operations.
* **Whitelist**: Some markets require addresses to be whitelisted before depositing. Check `isWhitelisted(marketId, address)` on WhitelistManager before attempting deposits.
* **MarketId**: Computed from ALL 8 Market struct fields, not just collateralAsset and referenceAsset. The same Market parameters produce the same MarketId on any chain.
* **CorkAdapter vs CorkPoolManager**: Use CorkAdapter (`safe*` functions) for production writes — it adds slippage and deadline protection. Use CorkPoolManager directly for reads.

***

## Links

* [Developer Quick Start](/developers/quick-start)
* [Contract Reference](/developers/contract-reference)
* [API Reference](/developers/api-reference)
* [Core Concepts](/core-concepts/cork-pool)
* [GitHub](https://github.com/Cork-Technology/phoenix)
* [Website](https://cork.tech)


