Kuest uses multiple smart contracts on Polygon for trading, market creation, and settlement.
Contract addresses
All addresses from src/lib/contracts.ts:
Core trading contracts
Contract Address Purpose USDC (Native) 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359Trading collateral USDC (Bridged) 0x2791bca1f2de4661ed88a30c99a7a9449aa84174Legacy USDC.e Conditional Tokens 0x4682048725865bf17067bd85fF518527A262A9C7Outcome token minting CTF Exchange 0xB5592f7CccA122558D2201e190826276f3a661cbOrder matching Neg Risk Exchange 0xef02d1Ea5B42432C4E99C2785d1a4020d2FB24F5Multi-outcome markets
Oracle and resolution
Contract Address Purpose UMA CTF Adapter 0x20088f6aa9D8D5947c9f002167355Cb332134bf8Oracle adapter UMA Neg Risk Adapter 0x724259Fe88100FE18C134324C4853975FBDa4d76Multi-outcome oracle Resolved By 0x559a18f929E47589521E4c61599E235Fd38A0c95Resolution authority
Safe wallet support
Contract Address Purpose Safe Proxy Factory 0x0202c1c426C77cEE55979e4fB3496288fAba8413Deploy Safe wallets Safe Multisend 0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761Batch transactions
Constants
export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'
export const ZERO_COLLECTION_ID = '0x0000000000000000000000000000000000000000000000000000000000000000'
Contract ABIs
USDC token
[
{
"name" : "balanceOf" ,
"type" : "function" ,
"stateMutability" : "view" ,
"inputs" : [{ "name" : "account" , "type" : "address" }],
"outputs" : [{ "name" : "balance" , "type" : "uint256" }]
},
{
"name" : "approve" ,
"type" : "function" ,
"stateMutability" : "nonpayable" ,
"inputs" : [
{ "name" : "spender" , "type" : "address" },
{ "name" : "amount" , "type" : "uint256" }
],
"outputs" : [{ "name" : "success" , "type" : "bool" }]
},
{
"name" : "transfer" ,
"type" : "function" ,
"stateMutability" : "nonpayable" ,
"inputs" : [
{ "name" : "to" , "type" : "address" },
{ "name" : "amount" , "type" : "uint256" }
],
"outputs" : [{ "name" : "success" , "type" : "bool" }]
}
]
Conditional Tokens
[
{
"name" : "splitPosition" ,
"type" : "function" ,
"inputs" : [
{ "name" : "collateralToken" , "type" : "address" },
{ "name" : "parentCollectionId" , "type" : "bytes32" },
{ "name" : "conditionId" , "type" : "bytes32" },
{ "name" : "partition" , "type" : "uint256[]" },
{ "name" : "amount" , "type" : "uint256" }
]
},
{
"name" : "mergePositions" ,
"type" : "function" ,
"inputs" : [
{ "name" : "collateralToken" , "type" : "address" },
{ "name" : "parentCollectionId" , "type" : "bytes32" },
{ "name" : "conditionId" , "type" : "bytes32" },
{ "name" : "partition" , "type" : "uint256[]" },
{ "name" : "amount" , "type" : "uint256" }
]
},
{
"name" : "redeemPositions" ,
"type" : "function" ,
"inputs" : [
{ "name" : "collateralToken" , "type" : "address" },
{ "name" : "parentCollectionId" , "type" : "bytes32" },
{ "name" : "conditionId" , "type" : "bytes32" },
{ "name" : "indexSets" , "type" : "uint256[]" }
]
}
]
Contract interactions
Approve USDC for trading
import { NATIVE_USDC_TOKEN_ADDRESS , CTF_EXCHANGE_ADDRESS } from '@/lib/contracts'
import { useWriteContract } from 'wagmi'
const { writeContract } = useWriteContract ()
// Approve unlimited USDC
await writeContract ({
address: NATIVE_USDC_TOKEN_ADDRESS ,
abi: erc20Abi ,
functionName: 'approve' ,
args: [
CTF_EXCHANGE_ADDRESS ,
BigInt ( '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' ),
],
})
Split USDC into outcome tokens
import { CONDITIONAL_TOKENS_CONTRACT } from '@/lib/contracts'
import { parseUnits } from 'viem'
// Split 10 USDC into YES/NO shares
await writeContract ({
address: CONDITIONAL_TOKENS_CONTRACT ,
abi: conditionalTokensAbi ,
functionName: 'splitPosition' ,
args: [
NATIVE_USDC_TOKEN_ADDRESS , // collateral
ZERO_COLLECTION_ID , // parent collection
conditionId , // market condition ID
[ 1 , 2 ], // partition (YES, NO)
parseUnits ( '10' , 6 ), // amount (10 USDC)
],
})
Redeem winning shares
// After market resolves to outcome index 0 (YES)
await writeContract ({
address: CONDITIONAL_TOKENS_CONTRACT ,
abi: conditionalTokensAbi ,
functionName: 'redeemPositions' ,
args: [
NATIVE_USDC_TOKEN_ADDRESS ,
ZERO_COLLECTION_ID ,
conditionId ,
[ 1 ], // index set for YES
],
})
Reading contract state
Check USDC allowance
import { useReadContract } from 'wagmi'
const { data : allowance } = useReadContract ({
address: NATIVE_USDC_TOKEN_ADDRESS ,
abi: erc20Abi ,
functionName: 'allowance' ,
args: [ userAddress , CTF_EXCHANGE_ADDRESS ],
})
const hasAllowance = allowance && allowance > 0 n
Get outcome token balance
const { data : balance } = useReadContract ({
address: CONDITIONAL_TOKENS_CONTRACT ,
abi: conditionalTokensAbi ,
functionName: 'balanceOf' ,
args: [ userAddress , positionId ],
})
console . log ( 'Outcome tokens:' , Number ( balance ) / 1e6 )
Check market resolution
const { data : payoutNumerators } = useReadContract ({
address: CONDITIONAL_TOKENS_CONTRACT ,
abi: conditionalTokensAbi ,
functionName: 'payoutNumerators' ,
args: [ conditionId , outcomeIndex ],
})
// If payoutNumerators[0] === 1, YES won
// If payoutNumerators[1] === 1, NO won
Event listening
Listen for USDC transfers
import { createPublicClient , http , parseAbiItem } from 'viem'
import { polygon } from 'viem/chains'
const client = createPublicClient ({
chain: polygon ,
transport: http (),
})
const unwatch = client . watchEvent ({
address: NATIVE_USDC_TOKEN_ADDRESS ,
event: parseAbiItem ( 'event Transfer(address indexed from, address indexed to, uint256 value)' ),
args: {
to: userAddress ,
},
onLogs : ( logs ) => {
console . log ( 'Received USDC:' , logs )
},
})
Listen for order fills
// Listen for trades on CTF Exchange
const unwatch = client . watchEvent ({
address: CTF_EXCHANGE_ADDRESS ,
event: parseAbiItem ( 'event OrderFilled(bytes32 indexed orderId, address indexed taker, uint256 fillAmount)' ),
onLogs : ( logs ) => {
console . log ( 'Order filled:' , logs )
},
})
Gas estimation
import { useEstimateGas } from 'wagmi'
const { data : estimatedGas } = useEstimateGas ({
to: CTF_EXCHANGE_ADDRESS ,
data: encodeFunctionData ({
abi: exchangeAbi ,
functionName: 'fillOrder' ,
args: [ order , signature ],
}),
})
console . log ( 'Estimated gas:' , estimatedGas )
Typical gas usage:
USDC approval: ~46,000 gas
Split position: ~180,000 gas
Merge position: ~120,000 gas
Redeem position: ~90,000 gas
Security considerations
Always verify contract addresses before interacting. Scammers may deploy fake contracts.
Verify on PolygonScan
Visit polygonscan.com
Search for contract address
Check “Contract” tab is verified
Verify code matches expected implementation
Check token approvals
// Revoke approval if no longer needed
await writeContract ({
address: NATIVE_USDC_TOKEN_ADDRESS ,
abi: erc20Abi ,
functionName: 'approve' ,
args: [
CTF_EXCHANGE_ADDRESS ,
0 n , // Revoke
],
})
Use revoke.cash to audit and revoke token approvals.
Multicall batching
Execute multiple operations in one transaction using Safe Multisend:
import { SAFE_MULTISEND_ADDRESS } from '@/lib/contracts'
// Batch: Approve USDC + Split position
const calls = [
{
to: NATIVE_USDC_TOKEN_ADDRESS ,
data: encodeFunctionData ({
abi: erc20Abi ,
functionName: 'approve' ,
args: [ CTF_EXCHANGE_ADDRESS , parseUnits ( '1000' , 6 )],
}),
},
{
to: CONDITIONAL_TOKENS_CONTRACT ,
data: encodeFunctionData ({
abi: conditionalTokensAbi ,
functionName: 'splitPosition' ,
args: [ NATIVE_USDC_TOKEN_ADDRESS , ZERO_COLLECTION_ID , conditionId , [ 1 , 2 ], parseUnits ( '10' , 6 )],
}),
},
]
// Execute via Multisend
await executeMultisend ( SAFE_MULTISEND_ADDRESS , calls )
Contract source code
Conditional Tokens Core prediction market contracts
CTF Exchange Order book exchange implementation
UMA Protocol Optimistic oracle contracts
Safe Contracts Multi-sig wallet contracts
Next steps
Polygon setup Configure Polygon network
USDC operations Learn USDC deposit and withdrawal
Trading API Place orders via API
UMA oracles How market resolution works