WethOver4800AtT24Resolver

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/WethOver4800AtT24Resolver.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/// @notice Minimal interface to your PredictionAMM.
interface IPredictionMarketMinimal {
    function closeMarket(uint256 marketId) external;
    function resolve(uint256 marketId, bool outcome) external;
    function tradingOpen(uint256 marketId) external view returns (bool);
    function getMarket(uint256 marketId)
        external
        view
        returns (
            uint256 yesSupply,
            uint256 noSupply,
            address resolver,
            bool resolved,
            bool outcome,
            uint256 pot,
            uint256 payoutPerShare,
            string memory desc
        );
}

/// @notice Minimal interface to CheckTheChain (CTC).
interface ICheckTheChain {
    function checkPrice(string calldata token)
        external
        view
        returns (uint256 price, string memory priceStr);
}

/**
 * @title WethOver4800AtT24Resolver
 * @notice YES iff WETH price in USDC (6 decimals) from CheckTheChain is strictly > 4800.000000,
 *         using a single snapshot taken at/after 24 hours from deployment.
 *
 * - CTC:       0x0000000000cDC1F8d393415455E382c30FBc0a84
 * - Token key: "WETH"
 * - Rule:      priceX6 > 4_800_000_000  => YES, else NO
 * - Flow:
 *     1) link(marketId) once; verifies this as market resolver.
 *     2) after earliestTs, poke(): snapshot CTC price (once), try to close market,
 *        and resolve if market is not open.
 */
contract WethOver4800AtT24Resolver {
    // ---- Constants / config ----
    ICheckTheChain public constant CTC = ICheckTheChain(0x0000000000cDC1F8d393415455E382c30FBc0a84);
    string public constant TOKEN_SYMBOL = "WETH";
    uint256 public constant STRIKE_X6 = 4_800_000_000; // 4800.000000 USDC (6 decimals)

    // ---- Immutable deps ----
    IPredictionMarketMinimal public immutable PM =
        IPredictionMarketMinimal(0x000000000088B4B43A69f8CDa34d93eD1d6f1431);
    uint256 public immutable earliestTs; // deployedAt + 24h

    // ---- State ----
    uint256 public marketId; // set via link()
    bool public observed; // sticky
    uint256 public priceX6AtObs; // cached USDC 6-dec price at observation

    // ---- Events ----
    event Linked(uint256 indexed marketId);
    event Observed(uint256 priceX6, string pretty);
    event Closed(uint256 indexed marketId, uint256 atTs);
    event Resolved(uint256 indexed marketId, bool yesOutcome);

    // ---- Errors ----
    error AlreadyLinked();
    error NotLinked();
    error WrongResolver();
    error TooEarly();
    error MarketStillOpen();

    constructor() payable {
        earliestTs = block.timestamp + 24 hours;
    }

    /// @notice One-time link; verifies this contract is the market's resolver.
    function link(uint256 _marketId) external {
        if (marketId != 0) revert AlreadyLinked();
        (,, address resolver,,,,,) = PM.getMarket(_marketId);
        if (resolver != address(this)) revert WrongResolver();
        marketId = _marketId;
        emit Linked(_marketId);
    }

    /// @notice Snapshot once at/after earliestTs, attempt to close, then resolve YES/NO.
    function poke() external {
        uint256 id = marketId;
        if (id == 0) revert NotLinked();
        if (block.timestamp < earliestTs) revert TooEarly();

        // Snapshot exactly once.
        if (!observed) {
            (uint256 px, string memory pretty) = CTC.checkPrice(TOKEN_SYMBOL);
            priceX6AtObs = px;
            observed = true;
            emit Observed(px, pretty);
        }

        // Try to close market if still open (will succeed only if PM.canClose = true).
        if (PM.tradingOpen(id)) {
            // Swallow failure if market isn't closable yet.
            try PM.closeMarket(id) {
                emit Closed(id, block.timestamp);
            } catch {}
        }

        // If still open, we cannot resolve yet.
        if (PM.tradingOpen(id)) revert MarketStillOpen();

        bool yes = (priceX6AtObs > STRIKE_X6);
        PM.resolve(id, yes);
        emit Resolved(id, yes);
    }

    /// @notice View helper for UIs.
    function preview()
        external
        view
        returns (
            uint256 nowTs,
            uint256 earliestAllowedTs,
            bool isLinked,
            bool isObserved,
            uint256 priceX6CurrentOrObserved,
            uint256 strikeX6,
            bool wouldResolveYes
        )
    {
        nowTs = block.timestamp;
        earliestAllowedTs = earliestTs;
        isLinked = (marketId != 0);
        isObserved = observed;
        strikeX6 = STRIKE_X6;

        if (observed) {
            priceX6CurrentOrObserved = priceX6AtObs;
        } else {
            (uint256 px,) = CTC.checkPrice(TOKEN_SYMBOL);
            priceX6CurrentOrObserved = px;
        }

        wouldResolveYes = (priceX6CurrentOrObserved > STRIKE_X6);
    }
}
"
    }
  },
  "settings": {
    "remappings": [
      "@solady/=lib/solady/",
      "@soledge/=lib/soledge/",
      "@forge/=lib/forge-std/src/",
      "forge-std/=lib/forge-std/src/",
      "solady/=lib/solady/src/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 9999999
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "prague",
    "viaIR": true
  }
}}

Tags:
Factory|addr:0x175645221539889904f45200d4b36f91115103f0|verified:true|block:23535856|tx:0xdd184bfc7c36e8c83c1129e691a3b0b4c7fc604961d370c9936a8f4c55ca878f|first_check:1759994672

Submitted on: 2025-10-09 09:24:32

Comments

Log in to comment.

No comments yet.