Skip to main content

Prerequisites

Before you begin, ensure you have:

Foundry Installed

Install from getfoundry.sh

Contract Addresses

UMA contract addresses for your target network

Whitelisted Token

An ERC20 token approved by UMA’s CollateralWhitelist

RPC Endpoint

Access to an Ethereum/Polygon RPC provider

Installation

1

Clone the repository

Clone the UMA CTF Adapter repository with submodules:
git clone https://github.com/Polymarket/uma-ctf-adapter.git --recurse-submodules
cd uma-ctf-adapter
2

Install dependencies

Update Forge dependencies:
forge update
3

Build contracts

Compile the contracts:
forge build
4

Run tests

Verify everything works:
forge test

Deploy the Adapter

You can deploy the adapter using either the provided deployment script or manually.
Create a .env file with your configuration:
.env
RPC_URL=https://polygon-rpc.com
PRIVATE_KEY=your_private_key_here
CTF_ADDRESS=0x...
FINDER_ADDRESS=0x...
OO_ADDRESS=0x...
Run the deployment script:
source deploy/scripts/deploy_adapter.sh
For production deployments on Polygon, see the official deployments page for verified contract addresses.

Initialize Your First Market

Once deployed, you can initialize a prediction market question.
1

Prepare ancillary data

Create the question text in a format compatible with UMA:
bytes memory ancillaryData = bytes("Q: Will ETH be above $2000 on Jan 1, 2025? A: 1 for yes, 0 for no.");
2

Choose market parameters

Select appropriate parameters for your market:
  • rewardToken: Address of whitelisted ERC20 (e.g., USDC)
  • reward: Amount to reward the proposer (e.g., 100 USDC)
  • proposalBond: Bond required from proposers (0 = use default)
  • liveness: Time before proposal is finalized (0 = use 2 hour default)
Reward and bond amounts should be sized appropriately based on the value at risk in your market. Higher value markets need higher rewards and bonds.
3

Call initialize

Initialize the market on the adapter:
bytes32 questionID = adapter.initialize(
    ancillaryData,
    address(usdc),           // rewardToken
    100 * 10**6,             // reward (100 USDC)
    0,                       // proposalBond (use default)
    0                        // liveness (use 2 hour default)
);

Monitor Your Market

After initialization, you can check the market status:
// Check if market is ready to resolve
const isReady = await adapter.ready(questionID);

// Get question data
const questionData = await adapter.getQuestion(questionID);
console.log("Request timestamp:", questionData.requestTimestamp);
console.log("Reward:", questionData.reward);
console.log("Resolved:", questionData.resolved);

Resolve Your Market

Once the Optimistic Oracle has a price available (after the liveness period):
// Check if ready to resolve
const ready = await adapter.ready(questionID);

if (ready) {
  // Anyone can call resolve
  const tx = await adapter.resolve(questionID);
  await tx.wait();
  
  console.log("Market resolved!");
}

Testing Locally

For local development and testing, use Foundry’s built-in testing framework:
test/YourTest.t.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import "forge-std/Test.sol";
import "../src/UmaCtfAdapter.sol";

contract AdapterTest is Test {
    UmaCtfAdapter adapter;
    
    function setUp() public {
        adapter = new UmaCtfAdapter(ctfAddress, finderAddress, ooAddress);
    }
    
    function testInitialize() public {
        bytes memory data = bytes("Q: Test question?");
        bytes32 questionID = adapter.initialize(
            data,
            address(token),
            100e6,
            0,
            0
        );
        
        assertTrue(adapter.isInitialized(questionID));
    }
}
Run your tests:
forge test -vvv

Common Issues

The reward token must be on UMA’s CollateralWhitelist. Check the Configuration page for approved tokens on your network.
Ancillary data must be non-empty and less than 8139 bytes after the initializer address is appended.
Each unique ancillary data string (including appended initializer address) can only be used once. Use different question text for each market.

Next Steps

Learn the Architecture

Understand how the adapter works under the hood

Integration Guide

Deep dive into market initialization parameters

API Reference

Explore the complete contract API

Admin Operations

Learn about administrative controls

Build docs developers (and LLMs) love