ListingOracle

Description:

Smart contract deployed on Ethereum with Factory, Oracle features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/ListingOracle.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "./interfaces/IStrategyIndex.sol";

/**
 * ListingOracle v1.9.2 (Mainnet-Ready)
 * ------------------------------------
 * - Integrates with external StrategyIndex for PunkLoopEngine.
 * - Tracks and updates the on-chain floor.
 * - Owner-tunable safety parameters.
 * - Optional updater whitelist (approveUpdater) for ConfigAll.s.sol compatibility.
 */

contract ListingOracle {
    address public owner;
    IStrategyIndex public strategy;

    // ---- Last observation ----
    uint256 public lastUpdateTs;
    uint256 public lastFloorWei;
    uint256 public lastSpreadBips;
    uint256 public lastListings;

    // ---- Tunables ----
    uint256 public floorCooldown = 600;   // seconds between updates
    uint256 public maxSpreadBips = 2000;  // 20% tolerance
    uint256 public retryDelay    = 60;    // retry delay on failure
    uint256 public minListings   = 15;    // min listings for validity

    // ---- Updater whitelist ----
    mapping(address => bool) public approvedUpdater;
    bool public whitelistMode;  // if false, anyone can call refreshFloor()

    // ---- Events ----
    event OwnerSet(address indexed owner);
    event StrategySet(address indexed strategy);
    event TunablesSet(uint256 floorCooldown, uint256 maxSpreadBips, uint256 retryDelay, uint256 minListings);
    event FloorUpdated(uint256 floorWei, uint256 listings, uint256 spreadBips);
    event UpdaterApproved(address indexed updater, bool approved);
    event WhitelistModeSet(bool enabled);

    // ---- Errors ----
    error NotOwner();
    error CooldownActive();
    error InvalidResponse();
    error TooFewListings();
    error NotApproved();

    modifier onlyOwner() {
        if (msg.sender != owner) revert NotOwner();
        _;
    }

    modifier onlyUpdater() {
        if (whitelistMode && !approvedUpdater[msg.sender] && msg.sender != owner) revert NotApproved();
        _;
    }

    constructor(address _strategy) {
        require(_strategy != address(0), "ADDR0");
        owner = msg.sender;
        strategy = IStrategyIndex(_strategy);
        emit OwnerSet(owner);
        emit StrategySet(_strategy);
    }

    // ---- Owner admin ----
    function setOwner(address _owner) external onlyOwner {
        require(_owner != address(0), "ADDR0");
        owner = _owner;
        emit OwnerSet(_owner);
    }

    function setStrategy(address _strategy) external onlyOwner {
        require(_strategy != address(0), "ADDR0");
        strategy = IStrategyIndex(_strategy);
        emit StrategySet(_strategy);
    }

    function setTunables(
        uint256 _floorCooldown,
        uint256 _maxSpreadBips,
        uint256 _retryDelay,
        uint256 _minListings
    ) external onlyOwner {
        require(_floorCooldown >= 60 && _retryDelay >= 30, "LOW_INTERVAL");
        require(_maxSpreadBips <= 10_000, "BIPS");
        floorCooldown = _floorCooldown;
        maxSpreadBips = _maxSpreadBips;
        retryDelay    = _retryDelay;
        minListings   = _minListings;
        emit TunablesSet(_floorCooldown, _maxSpreadBips, _retryDelay, _minListings);
    }

    // ---- Updater whitelist management ----
    function approveUpdater(address updater, bool approved) external onlyOwner {
        approvedUpdater[updater] = approved;
        emit UpdaterApproved(updater, approved);
    }

    function setWhitelistMode(bool enabled) external onlyOwner {
        whitelistMode = enabled;
        emit WhitelistModeSet(enabled);
    }

    // ---- Public view helpers ----
    function latestFloor() external view returns (uint256) {
        return lastFloorWei;
    }

    function preferredListing()
        external
        view
        returns (bool ok, uint256 punkId, uint256 priceWei, address updater)
    {
        try strategy.globalFloor() returns (uint256 floor) {
            return (floor > 0, 0, floor, address(strategy));
        } catch {
            return (false, 0, 0, address(strategy));
        }
    }

    // ---- Active updater ----
    function refreshFloor() external onlyUpdater {
        uint256 nowTs = block.timestamp;
        if (nowTs < lastUpdateTs + floorCooldown) revert CooldownActive();

        (bool ok, , uint256 newFloor, ) = this.preferredListing();
        if (!ok || newFloor == 0) revert InvalidResponse();

        uint256 prevFloor = lastFloorWei;
        if (prevFloor > 0) {
            uint256 spread = prevFloor > newFloor
                ? ((prevFloor - newFloor) * 10_000) / prevFloor
                : ((newFloor - prevFloor) * 10_000) / prevFloor;
            if (spread > maxSpreadBips) revert InvalidResponse();
            lastSpreadBips = spread;
        }

        // Placeholder: assume listings >= minListings for trusted oracle feed
        uint256 listings = minListings;
        if (listings < minListings) revert TooFewListings();

        lastUpdateTs = nowTs;
        lastFloorWei = newFloor;
        lastListings = listings;

        emit FloorUpdated(newFloor, listings, lastSpreadBips);
    }

    receive() external payable {}
}
"
    },
    "contracts/interfaces/IStrategyIndex.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IStrategyIndex {
    /// Buy a Punk and relist it on-chain.
    function buyPunkAndRelist(uint256 punkId) external payable;

    /// Return the global floor price (in wei) for listed Punks.
    function globalFloor() external view returns (uint256);

    /// (Optional) Return the listing price for a specific Punk.
    function getPunkPrice(uint256 punkId) external view returns (uint256);
}
"
    }
  },
  "settings": {
    "remappings": [
      "forge-std/=lib/forge-std/src/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 400
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs",
      "appendCBOR": true
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "cancun",
    "viaIR": true
  }
}}

Tags:
Factory, Oracle|addr:0xd7708d19bce58963f7821fc20dc7e939ce85219c|verified:true|block:23683608|tx:0xba111481c08c97c86abc0991acc3a3f13203fc659ed1ed448d960d05222e66bb|first_check:1761754869

Submitted on: 2025-10-29 17:21:09

Comments

Log in to comment.

No comments yet.