Skip to main content

Common Issues

Resolution Issues

Symptoms:
  • Resolution time has passed but market not resolved
  • getResolution() still shows resolved: false
Possible Causes:
  1. Data source delay: External API hasn’t updated yet
  2. Low confidence: AI waiting for more data confirmation
  3. Network congestion: Transaction stuck in mempool
  4. Criteria unclear: AI unable to parse criteria
Solutions:
// Check resolution status
(bool resolved, uint256 outcome, uint256 confidence, uint256 timestamp) =
    delphaiOracle.getResolution(marketId);

if (!resolved) {
    // Check if resolution time has passed
    uint256 resolutionTime = delphaiOracle.getResolutionTime(marketId);
    require(block.timestamp >= resolutionTime, "Too early");

    // If more than 1 hour late, contact support
    if (block.timestamp > resolutionTime + 1 hours) {
        // Implement fallback or emergency resolution
    }
}
Prevention:
  • Add buffer time between event end and resolution time
  • Specify multiple reliable data sources
  • Write clear, unambiguous resolution criteria
Symptoms:
  • Resolution submitted but confidence < 90%
  • Your contract rejects low confidence resolutions
Common Causes:
IssueSolution
Vague criteriaBe more specific about data sources and logic
Unreliable data sourceUse established providers (CoinGecko, ESPN, etc.)
Ambiguous questionRephrase with clear YES/NO logic
Data unavailableWrong API endpoint or source offline
Premature resolutionResolution time before data is available
Example Fix:Bad criteria (causes low confidence):
"Check if Bitcoin price is high by end of year"
Good criteria (high confidence):
"Use CoinGecko API endpoint /api/v3/simple/price?ids=bitcoin
Check BTC price at 2025-12-31 23:59:59 UTC
If price >= $100,000 → YES
If price < $100,000 → NO
Backup: CoinMarketCap if CoinGecko down"
Debugging:
// Check resolution details
const resolution = await oracle.getResolution(marketId);
const proof = await oracle.getProof(marketId);

console.log('Confidence:', resolution.confidence);
console.log('Proof:', ethers.utils.toUtf8String(proof));

// Proof shows what data sources were queried and why confidence is low
Symptoms:
  • Resolution fails or delays
  • Error: “Data source unavailable”
Solutions:
  1. Always specify backup sources:
Primary: CoinGecko API
Backup: CoinMarketCap API
Tertiary: Binance API
Fallback: Delay 1 hour and retry
  1. Use reliable providers:
  • ✅ CoinGecko, CoinMarketCap (crypto)
  • ✅ ESPN, Official League APIs (sports)
  • ✅ NOAA, OpenWeatherMap (weather)
  • ❌ Unknown or unreliable APIs
  1. Test data source accessibility:
# Test if API is reachable
curl "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd"
  1. Check API rate limits:
  • Some free APIs have rate limits
  • Use paid tiers for critical markets
Symptoms:
  • Resolution outcome doesn’t match expected result
  • Users dispute the resolution
Investigation Steps:
// Get resolution proof
bytes memory proof = delphaiOracle.getProof(marketId);

// Get attestation
(bytes memory attestation, bytes32 codeHash, address teeAddress) =
    delphaiOracle.getAttestation(marketId);

// Proof contains:
// - Data sources queried
// - Raw data received
// - Resolution logic applied
// - Timestamps
Common Reasons:
ReasonFix
Wrong data source queriedVerify exact API endpoint in criteria
Timing issueCheck if data was available at resolution time
Criteria misunderstoodRephrase criteria more clearly
Data source errorUse multiple sources for verification
If Resolution is Wrong:
  1. Review proof and attestation data
  2. Check if criteria were ambiguous
  3. Implement dispute mechanism in your platform
  4. Contact support with proof if TEE malfunction suspected

Integration Issues

Symptoms:
  • Market resolved on oracle but your contract not updated
  • ResolutionSubmitted event fired but your callback didn’t execute
Checklist:
// ✅ 1. Does your contract implement the interface?
contract MyMarket is IPlatformCallback {
    // ...
}

// ✅ 2. Is the function marked external?
function resolveMarket(
    uint256 marketId,
    uint256 outcome,
    bytes memory attestation,
    bytes memory proof
) external override {  // Must be external
    // ...
}

// ✅ 3. Does it have correct access control?
function resolveMarket(...) external {
    // Should only check it's from oracle
    require(msg.sender == delphaiOracle, "Only oracle");
    // Don't add other restrictions that might block it
}

// ✅ 4. Does callback revert?
function resolveMarket(...) external {
    // Avoid require() that might fail
    require(markets[marketId].exists, "Market not found"); // Could fail!

    // Use try-catch or check conditions first
    if (!markets[marketId].exists) return;
}
Testing Callback:
// Test callback directly on testnet
const platformContract = await ethers.getContractAt("MyMarket", address);

// Call resolveMarket manually to test
await platformContract.resolveMarket(
    marketId,
    1, // outcome
    "0x", // attestation (empty for test)
    "0x"  // proof (empty for test)
);

// Should update market state without reverting
Debug Failed Callback:
// Listen for ResolutionCallbackFailed event
oracle.on('ResolutionCallbackFailed', (marketId, platform, reason) => {
    console.error('Callback failed!');
    console.error('Market:', marketId.toString());
    console.error('Reason:', ethers.utils.toUtf8String(reason));
});
Symptoms:
  • verifyAttestation() returns false
  • Your contract rejects resolutions
Common Issues:
  1. Code hash not approved:
// Check if code hash is approved
bytes32 codeHash = extractCodeHash(attestation);

if (!approvedCodeHashes[codeHash]) {
    // Add to approved hashes
    approvedCodeHashes[codeHash] = true;

    // Or get approved hashes from oracle
    require(
        delphaiOracle.isApprovedCodeHash(codeHash),
        "Unknown AI version"
    );
}
  1. Attestation expired:
// Check attestation timestamp
uint256 attestationTime = extractTimestamp(attestation);
require(
    block.timestamp - attestationTime <= 1 hours,
    "Attestation too old"
);
  1. Wrong verification library:
// Use correct TEE verification library
import "@delphai/contracts/TEEVerifier.sol";

function verifyAttestation(bytes memory attestation)
    internal
    view
    returns (bool)
{
    return TEEVerifier.verify(attestation);
}
  1. TEE address not authorized:
// Check TEE address
(, , address teeAddress) = delphaiOracle.getAttestation(marketId);
require(
    delphaiOracle.isAuthorizedTEE(teeAddress),
    "Unauthorized TEE"
);
Testing:
// Test attestation verification
const attestation = await oracle.getAttestation(marketId);
const isValid = await TEEVerifier.verify(attestation.attestation);
console.log('Attestation valid:', isValid);
Symptoms:
  • Callback transactions cost too much gas
  • Resolution requests expensive
Optimization Tips:
  1. Efficient storage:
// ❌ Expensive: Store full strings
struct Market {
    string question;
    string criteria;
}

// ✅ Efficient: Store hashes
struct Market {
    bytes32 questionHash;
    bytes32 criteriaHash;
}
  1. Minimize callback logic:
function resolveMarket(...) external {
    // ✅ Simple: Just update state
    markets[marketId].resolved = true;
    markets[marketId].outcome = outcome;

    // ❌ Expensive: Complex calculations
    // Do these in separate user-triggered transactions
    // calculateAndDistributeWinnings(marketId);
}
  1. Batch operations:
// If resolving multiple markets, batch them
function resolveMarkets(
    uint256[] memory marketIds,
    uint256[] memory outcomes,
    bytes[] memory attestations
) external {
    for (uint i = 0; i < marketIds.length; i++) {
        _resolveMarket(marketIds[i], outcomes[i], attestations[i]);
    }
}
  1. Use events instead of storage:
// Store minimal data onchain
markets[marketId].outcome = outcome;

// Emit detailed data in events (cheaper)
emit MarketResolved(marketId, outcome, attestation, proof);
Common Issues:
  1. Wrong oracle address:
constructor(address _oracle) {
    require(_oracle != address(0), "Invalid oracle");
    delphaiOracle = _oracle;
}
  1. Missing interface implementation:
// Must implement IPlatformCallback
contract MyMarket is IPlatformCallback {
    function resolveMarket(...) external override {
        // Implementation
    }
}
  1. Contract size too large:
# Check contract size
forge build --sizes

# If too large, optimize:
# - Remove unused functions
# - Use libraries for common code
# - Enable optimizer
Deployment Checklist:
  • ✅ Correct network (mainnet/testnet)
  • ✅ Correct oracle address for network
  • ✅ Sufficient gas for deployment
  • ✅ Contract verified on block explorer

Network & Infrastructure Issues

Symptoms:
  • Transaction pending for long time
  • Resolution not confirming
Solutions:
  1. Check gas price:
// Check current gas price
const gasPrice = await provider.getGasPrice();
console.log('Current gas:', ethers.utils.formatUnits(gasPrice, 'gwei'));

// Send with higher gas if needed
const tx = await oracle.requestResolution(..., {
    gasPrice: gasPrice.mul(120).div(100) // 20% higher
});
  1. Speed up transaction:
// Replace transaction with higher gas
const newTx = await signer.sendTransaction({
    ...originalTx,
    nonce: originalTx.nonce, // Same nonce
    gasPrice: higherGasPrice  // Higher gas
});
  1. Cancel transaction:
// Send 0 ETH to yourself with same nonce but higher gas
await signer.sendTransaction({
    to: signer.address,
    value: 0,
    nonce: stuckTx.nonce,
    gasPrice: higherGasPrice
});
Symptoms:
  • Contract calls failing intermittently
  • “Execution reverted” with no reason
Solutions:
  1. Use reliable RPC providers:
// Use multiple providers as fallback
const providers = [
    new ethers.providers.JsonRpcProvider('https://eth-mainnet.alchemyapi.io/...'),
    new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/...'),
    new ethers.providers.JsonRpcProvider('https://eth-mainnet.public.blastapi.io')
];

// Fallback provider
const provider = new ethers.providers.FallbackProvider(providers);
  1. Implement retry logic:
async function callWithRetry(fn, retries = 3) {
    for (let i = 0; i < retries; i++) {
        try {
            return await fn();
        } catch (error) {
            if (i === retries - 1) throw error;
            await sleep(1000 * Math.pow(2, i)); // Exponential backoff
        }
    }
}

// Usage
const resolution = await callWithRetry(() =>
    oracle.getResolution(marketId)
);

Debugging Tools

Check Resolution Status

// Get complete resolution info
async function debugResolution(marketId) {
    const oracle = new ethers.Contract(oracleAddress, abi, provider);

    // Basic info
    const resolution = await oracle.getResolution(marketId);
    console.log('Resolved:', resolution.resolved);
    console.log('Outcome:', resolution.outcome.toString());
    console.log('Confidence:', resolution.confidence.toString());
    console.log('Timestamp:', new Date(resolution.timestamp * 1000));

    if (resolution.resolved) {
        // Get attestation
        const attestation = await oracle.getAttestation(marketId);
        console.log('Code Hash:', attestation.codeHash);
        console.log('TEE Address:', attestation.teeAddress);

        // Get proof
        const proof = await oracle.getProof(marketId);
        console.log('Proof:', ethers.utils.toUtf8String(proof));
    } else {
        // Get scheduled time
        const resolutionTime = await oracle.getResolutionTime(marketId);
        const now = Math.floor(Date.now() / 1000);

        if (now < resolutionTime) {
            console.log('Resolution scheduled for:', new Date(resolutionTime * 1000));
            console.log('Time remaining:', (resolutionTime - now) / 60, 'minutes');
        } else {
            console.log('⚠️ Resolution time passed but not resolved yet');
            console.log('Overdue by:', (now - resolutionTime) / 60, 'minutes');
        }
    }
}

Monitor Events

// Monitor oracle events for your markets
async function monitorMarket(marketId) {
    const oracle = new ethers.Contract(oracleAddress, abi, provider);

    // Listen for resolution
    const filter = oracle.filters.ResolutionSubmitted(marketId);

    oracle.on(filter, (
        marketId, platform, outcome, confidence, codeHash, attestation, proof, timestamp
    ) => {
        console.log('✅ Market resolved!');
        console.log('Outcome:', outcome.toString());
        console.log('Confidence:', confidence.toString());
    });

    // Listen for callback failures
    const failFilter = oracle.filters.ResolutionCallbackFailed(marketId);

    oracle.on(failFilter, (marketId, platform, reason) => {
        console.error('❌ Callback failed!');
        console.error('Reason:', ethers.utils.toUtf8String(reason));
    });
}

Test Callback Locally

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

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

contract MyMarketTest is Test {
    MyMarket market;
    address oracle = address(0x123);

    function setUp() public {
        market = new MyMarket(oracle);
    }

    function testResolveMarket() public {
        // Create market
        uint256 marketId = market.createMarket("Test question");

        // Mock oracle calling resolveMarket
        vm.prank(oracle);
        market.resolveMarket(
            marketId,
            1, // outcome
            "", // attestation
            ""  // proof
        );

        // Check market was updated
        assertTrue(market.isResolved(marketId));
        assertEq(market.getOutcome(marketId), 1);
    }
}

Getting Help

I