Skip to content

phoenix-protocol-labs/phoenix

Repository files navigation

Phoenix Protocol

On-chain perpetual autocallable structured products backed by real assets

Chainlink Convergence Hackathon 2026 | DeFi & Tokenization Track

Live App

Powered by Chainlink CRE

Phoenix uses Chainlink's Compute Runtime Environment (CRE) as the core automation engine:

  • 19 vaults observed by a single CRE workflow across 6 data sources
  • DON consensus via consensusMedianAggregation() -- no single point of failure
  • Cron-triggered barrier evaluation -> signed onReport() delivery
  • Defense-in-depth: circuit breakers in both CRE workflow AND on-chain contracts

What is Phoenix?

Structured products are a multi-trillion dollar market in traditional finance. Autocalls, reverse convertibles, and capital-protected notes make up a significant share of institutional derivative trading. Yet in DeFi, these products are virtually nonexistent -- the ecosystem has basic yield vaults and vanilla options, but nothing that replicates the richness and conditional payoff mechanics of TradFi structured products.

Phoenix Protocol brings perpetual autocall vaults on-chain, powered by Chainlink CRE (Compute Runtime Environment) to automate the entire observation-evaluation-settlement pipeline. A single CRE workflow observes prices from five different data sources, evaluates three-tier barrier conditions, and writes settlement actions directly to the blockchain -- all without manual intervention or centralized keepers.

The vault holds the actual underlying -- tokenized equities (xStocks via Backed Finance) or crypto assets (wstETH) -- not a USDC pool tracking a price feed. Two sides take opposing views: Side A deposits the asset and earns USDC coupons, Side B deposits USDC and buys crash protection. The smart contract is the clearinghouse. No bank, no issuer.


Architecture Overview

                        Frontend
                   (React + Vite + wagmi)
                          |
                          v
          +-------------------------------+
          |        Smart Contracts        |
          | Factory + Vault + Settlement  |
          +-------------------------------+
               |         |          |
               v         v          v
         Chainlink CRE  CowSwap   Side A / Side B
      (Cron + HTTP + EVM) GPv2    (asset + USDC pools)
               |
     +---------+---------+---------+---------+
     |         |         |         |         |
   Pendle  Hyperliquid  Aave  DeFi Llama  xStocks
  (YT APY) (perp mid) (rates) (prices)  (stocks)

Two-Sided Vault Model

Side A (Yield)                          Side B (Hedge)
  deposits underlying asset               deposits USDC
  earns USDC coupons from B               pays fixed coupons to A
  risk: partial liquidation on KI          reward: USDC from KI liquidation
           |                                        |
           +---------> PerpetualVault <-------------+
                            |
                    PerpetualSettlement
                            |
                      CRE Oracle (onReport)
                            |
                    Barrier evaluation
                            |
              CONTINUE | PAY_COUPON | CYCLE_RESET | KNOCK_IN

Key Features

1. Two-Sided Asset-Backed Vaults

Side A (Yield) -- Deposits the underlying asset (xTSLA, wstETH, etc.). Earns periodic USDC coupons from Side B. On knock-in, a portion of holdings is liquidated via CowSwap. "I already hold this asset. I want yield on it."

Side B (Hedge) -- Deposits USDC. Pays fixed coupons. On knock-in, receives USDC from the liquidation of A's asset. "I want defined-cost crash protection."

2. Phoenix Memory Coupon

When a coupon is missed (price falls between the knock-in and coupon barriers), the missed coupon is not lost -- it is remembered. On the next observation where a coupon is paid or the cycle resets, all previously missed coupons are paid retroactively. A knock-in event forfeits all accumulated missed coupons. Memory is capped at a configurable depth cap per product.

Example scenario (2% coupon per period, $1.00 strike):

Period Price Action Missed Count Payout
1 $0.96 PAY_COUPON 0 $0.02 (current)
2 $0.70 CONTINUE 1 $0.00 (missed, remembered)
3 $0.72 CONTINUE 2 $0.00 (missed, remembered)
4 $0.96 PAY_COUPON 0 $0.06 (current + 2 memory)

3. Multi-Source Data Architecture

A single CRE workflow routes to five different external APIs via a discriminated union pattern in the configuration. Each vault specifies its data source type and parameters, and the workflow dynamically dispatches to the correct fetch function at runtime.

4. CRE-Powered Settlement

The full observation lifecycle runs through Chainlink CRE: cron trigger fires, HTTP capabilities fetch prices with DON consensus, barrier logic executes in WASM, and the signed report is written on-chain via IReceiver.onReport(). No manual keepers, no centralized servers. The settlement contract validates CRE workflow metadata (author + name hash) and re-validates the submitted action against on-chain barriers.

5. Perpetual Cycles

No expiry. After max periods or cycle reset, the cycle resets with the strike price set to the current market price. Four actions: CONTINUE (coupon missed, remembered), PAY_COUPON (pays current + memory), CYCLE_RESET (settles and resets), KNOCK_IN (liquidation, memory forfeited). No dead vaults, no redeployment.

6. CowSwap GPv2 Two-Phase Liquidation

Knock-in settlement uses CowSwap's GPv2Settlement for on-chain liquidation:

  1. Initiate: Calculate loss ratio, approve GPv2 VaultRelayer, set liquidation PENDING, block vault operations
  2. PreSign: Validate order parameters against pending liquidation, presign on GPv2Settlement
  3. Finalize: Verify USDC proceeds meet slippage tolerance, credit Side B (capped at expected to prevent donation attacks)
  4. Cancel: If order unfilled after 1-hour deadline, save for retry, revoke approval, resume
  5. Retry: Re-initiate a previously failed/cancelled liquidation

7. Factory Pattern

The PerpetualFactory contract creates new vaults with fully configurable parameters: underlying asset, barrier levels, coupon rate, periods per cycle, memory depth cap, and slippage tolerance. Each vault is a standalone contract registered with the shared settlement engine. Validates parameter ordering (autocall > coupon > knock-in), coupon rate 0--50%, and memory depth > 0.


Product Mechanics

An autocall is a structured product with periodic observations. At each observation date, the CRE workflow fetches the current price and evaluates it against three barrier levels:

Observation Date (CRE Cron fires)
        |
   Fetch price from data source
        |
        v
  price >= autocall barrier (e.g. 105%)
        |
   +----+----+
   | YES      | NO
   v          v
 CYCLE_RESET  price >= coupon barrier (e.g. 95%)
 (all coupons      AND price < autocall barrier
  + memory,        |
  cycle resets)    +----+----+
                   | YES      | NO
                   v          v
              PAY_COUPON    price <= knock-in barrier (e.g. 75%)
              (+ memory        |
               coupons)   +----+----+
                          | YES      | NO
                          v          v
                       KNOCK_IN    CONTINUE
                       (liquidation, (missed,
                        memory       remembered)
                        forfeited)

Data Sources

Source Type API Assets
Pendle Implied APY api-v2.pendle.finance uniETH YT, sUSDai YT, weETH YT, wstETH YT
Hyperliquid Perp Mid-Price api.hyperliquid.xyz ETH, BTC, SOL
xStocks Stock Price xstocks.finance TSLA, AAPL, NVDA
Aave (DeFi Llama) Supply Rate yields.llama.fi WETH, USDC, USDT, sGHO
DeFi Llama Token Price coins.llama.fi ETH, BTC, SOL, stETH, wstETH

All sources are fetched through the CRE HTTPClient with DON median aggregation for consensus.


Vault Catalog (19 Vaults)

Category Vaults Data Source Autocall Coupon Knock-in Coupon Rate
Spot ETH, BTC, SOL, stETH, wstETH DeFi Llama 105% 95% 75% 2--2.5%
Perp ETH, BTC, SOL Hyperliquid 105% 95% 75% 2--2.5%
Yield uniETH YT, sUSDai YT, weETH YT, wstETH YT Pendle 110% 90% 60% 2--2.5%
Rate Aave WETH, USDC, USDT, sGHO DeFi Llama 110% 90% 60% 1.5%
Equity TSLA, AAPL, NVDA xStocks 110% 90% 70% 2.5--3%

All vaults use 6 periods per cycle and memory depth cap of 4.


Tech Stack

Layer Technology Purpose
Contracts Solidity 0.8.24, Foundry, OpenZeppelin v5 Vault, settlement, factory
Oracle Chainlink CRE, TypeScript/WASM Price observation, barrier evaluation, settlement
Liquidation CowSwap GPv2Settlement On-chain knock-in asset liquidation
Frontend React 18, Vite, Tailwind CSS, wagmi v2, RainbowKit Wallet interaction, vault browsing
Network Ethereum Sepolia (chainId 11155111) Deployment target

Project Structure

contracts/
  src/
    PerpetualSettlement.sol   -- CRE receiver, perpetual cycles, memory coupons
    PerpetualVault.sol        -- Two-sided vault (asset + USDC), CowSwap liquidation
    PerpetualFactory.sol      -- Vault creation with asset-backed params
    MockUSDC.sol              -- Test token
    MockAsset.sol             -- Mock underlying asset for testing
    MockCowSwap.sol           -- Mock CowSwap for testing
    interfaces/
      IReceiver.sol           -- CRE-mandated receiver interface
      IPerpetualSettlement.sol -- Settlement interface and types
      ICowSwapSettlement.sol  -- Legacy CowSwap interface
      IGPv2Settlement.sol     -- GPv2Settlement interface
    libraries/
      GPv2OrderLib.sol        -- Order hashing and UID computation
  test/
    PerpetualSettlement.t.sol -- 50 tests
    PerpetualVault.t.sol      -- 68 tests
    PerpetualVaultCow.t.sol   -- 31 tests (CowSwap two-phase liquidation)
    PerpetualIntegration.t.sol -- 6 tests
  script/
    DeployPerpetualCow.s.sol  -- Deployment script (GPv2 mode, 19 vaults)

cre-workflow/
  src/
    workflows/
      perpetual-observation/  -- CRE workflow
        index.ts              -- Perpetual workflow (dynamic strike from getCycleState)
        abi.ts                -- Perpetual settlement ABI
        config.json           -- 19-product configuration
        workflow.yaml         -- CRE workflow settings
  project.yaml                -- CRE project settings (RPCs, chain config)

frontend/
  src/
    config/
      perpetualAddresses.ts   -- Deployed contract addresses + vault metadata
    lib/
      perpetualTypes.ts       -- TypeScript interfaces for on-chain structs
    hooks/
      usePerpetualVaults.ts   -- Multicall: factory -> vault -> settlement
      usePerpetualVaultDetails.ts -- Single vault detail + cycle history
    components/
      TwoSidedDeposit.tsx     -- Side A/B deposit widget
      CycleHistory.tsx        -- Archived cycle records table
    pages/
      VaultListPage.tsx       -- Vault list (earn/hedge mode)
      VaultDetailPage.tsx     -- Vault detail (metrics, barriers, deposit, history)
      docs/                   -- Documentation pages

Getting Started

Prerequisites

Contracts

cd contracts
forge build
forge test -vvv

CRE Workflow

cd cre-workflow
bun install
cre workflow simulate . -T local-simulation --non-interactive --trigger-index 0

Frontend

cd frontend
bun install
bun dev

Deployed Contracts (Ethereum Sepolia)

Contract Address
PerpetualSettlement 0xcbe9B34CDbD9Bb38b853fb58E0016A6AC0FC06Bb
PerpetualFactory 0x8840b23aFb4E5696312B7Fb24ea01EFB8c90D2b2
MockUSDC 0x5b564dcC5BeBdC348650F0FCcCa71FA9a7fF101b

Deployer: 0x8Fd983b62Ab8Cb7df019fD8B5B5D333E3D9A16AD

19 vaults deployed across 5 categories, each seeded with initial liquidity on both sides.


Testing

219 tests across 6 test files:

Test File Tests Coverage
PerpetualSettlement.t.sol 50 All 4 actions, cycle management, memory depth cap, multi-cycle, knock-in recovery, relay auth, ERC165, barrier validation, circuit breaker, minimum observation interval
PerpetualVault.t.sol 68 Deposits (A/B), withdrawals, dynamic coupon rate scaling, share accounting, multi-user pro-rata, donation attack mitigation, rebasing, soft cap, fuzz tests
PerpetualVaultCow.t.sol 31 Two-phase CowSwap liquidation, preSignOrder validation, finalize with proceeds, cancel after deadline, retry liquidation, deposits/withdrawals/observations blocked during pending liquidation, fuzz tests
PerpetualIntegration.t.sol 6 Full lifecycle happy path, knock-in liquidation + withdrawal, multi-user pro-rata, mid-cycle deposits, 3-cycle run, factory creates vault
cd contracts
forge test -vvv

All 219 tests pass.


Chainlink CRE Integration -- All Files

CRE Workflow (TypeScript, compiled to WASM)

File Role
cre-workflow/src/workflows/perpetual-observation/index.ts Main entry point -- cron trigger, 5 data source handlers (DeFi Llama, Hyperliquid, Pendle, Aave, xStocks), barrier evaluation, consensusMedianAggregation(), on-chain write via IReceiver.onReport()
cre-workflow/src/workflows/perpetual-observation/logic.ts Pure barrier logic -- evaluateBarriers(), validatePrice() (circuit breakers: max price, 50% deviation), toBigInt18(), fetchWithRetry()
cre-workflow/src/workflows/perpetual-observation/abi.ts Settlement contract ABI for getCycleState() and getProductParams() reads, Action enum
cre-workflow/src/workflows/perpetual-observation/config-batch-1.json Batch 1 config: PIDs 0-4 (DeFi Llama spot: ETH, BTC, SOL, stETH, wstETH)
cre-workflow/src/workflows/perpetual-observation/config-batch-2.json Batch 2 config: PIDs 5-9 (Hyperliquid perps + Pendle YT)
cre-workflow/src/workflows/perpetual-observation/config-batch-3.json Batch 3 config: PIDs 10-14 (Pendle YT + Aave rates)
cre-workflow/src/workflows/perpetual-observation/config-batch-4.json Batch 4 config: PIDs 15-18 (Aave sGHO + xStocks equities)
cre-workflow/src/workflows/perpetual-observation/workflow.yaml CRE workflow settings (8 targets: 4 local + 4 staging batches)
cre-workflow/project.yaml.example CRE project settings template (RPC endpoints per batch)

CRE Workflow Tests

File Tests
cre-workflow/src/workflows/perpetual-observation/__tests__/barriers.test.ts 20 tests -- all barrier regions, exact boundaries, custom params
cre-workflow/src/workflows/perpetual-observation/__tests__/validation.test.ts 32 tests -- zero/negative prices, max bounds, deviation circuit breaker
cre-workflow/src/workflows/perpetual-observation/__tests__/utils.test.ts 20 tests -- toBigInt18 precision, fetchWithRetry logic

On-Chain Contracts (Solidity -- IReceiver implementation)

File Role
contracts/src/interfaces/IReceiver.sol CRE-mandated receiver interface: onReport(bytes metadata, bytes report)
contracts/src/PerpetualSettlement.sol IReceiver implementation -- validates CRE workflow author + name hash from metadata, decodes report (productId, price, action), enforces circuit breakers (MAX_PRICE, 50% deviation, 1h min interval), re-validates action against on-chain barriers, routes to PAY_COUPON / CYCLE_RESET / KNOCK_IN / CONTINUE with memory coupon logic
contracts/src/interfaces/IPerpetualSettlement.sol Settlement types: ProductParams, CycleState, Action enum, CycleRecord

CRE Workflow Deep Dive

The CRE workflow (index.ts) implements a four-step pipeline executed by the Chainlink DON:

Step 0 -- Gate check: Read getCycleState() from the settlement contract. Read dynamic strikePrice for barrier evaluation (resets each cycle).

Step 1 -- Fetch price: Route to the correct data source handler based on the discriminated union config:

  • pendle -- GET request to Pendle Finance API, extract implied APY
  • hyperliquid_perp -- POST to Hyperliquid info endpoint with allMids, extract mid-price for the asset
  • aave_rate -- GET from DeFi Llama Yields API, find pool by UUID, extract APY
  • defillama_price -- GET from DeFi Llama Coins API, extract token price
  • xstocks -- GET from xStocks Finance API, extract stock price

Step 2 -- Read params: Call getProductParams() on the settlement contract to get barrier levels and coupon rate.

Step 3 -- Evaluate barriers: Compare the fetched price against autocall, coupon, and knock-in barrier prices. >= for autocall/coupon, <= for knock-in. Return the appropriate Action.

Step 4 -- Write on-chain: ABI-encode the report payload (productId, price, action), prepare a signed report via runtime.report(), and submit via evmClient.writeReport() to the settlement contract's onReport() function.

All HTTP fetches use consensusMedianAggregation() so that DON nodes independently fetch prices and reach consensus on the median value before writing on-chain.


How CRE Enables This

Without Chainlink CRE, building this protocol would require:

  • A centralized keeper service to trigger observations on schedule
  • Manual price fetching with no consensus or verification
  • Trust assumptions around price data integrity
  • Custom infrastructure for report signing and on-chain delivery

CRE provides all of this out of the box: cron scheduling, HTTP fetching with DON consensus, cryptographic report signing, and verified on-chain delivery via IReceiver. The workflow compiles to WASM for deterministic execution across all DON nodes, and the median aggregation ensures no single node can manipulate the price observation.


Demo Videos

Scenario Video
Full Protocol Overview video.mp4
Bull Market -- Early Redemption bull-market-early-redemption.mp4
Bear Market -- Capital Protection (Side B) bear-market-capital-protection.mp4
Bear Market -- Capital Loss (Knock-in) bear-market-capital-loss.mp4

Demo Walkthrough

  1. Visit the live app and connect your wallet (Ethereum Sepolia)
  2. Browse vaults at /app/earn (Side A) or /app/hedge (Side B)
  3. Open a vault detail page to view barrier levels, cycle progress, and Side A/B ratio
  4. Mint test USDC and approve the vault
  5. Deposit into your chosen side (underlying asset for A, USDC for B)
  6. CRE workflow observes prices on cron schedule and evaluates barriers
  7. View the observation timeline showing each period's action and Phoenix memory coupon behavior
  8. Request a withdrawal, wait 1 hour, then execute to receive your proportional payout

License

MIT

About

On-chain Structured Products Protocol

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors