PriceOracleFullERC165

Description:

Smart contract deployed on Ethereum with Oracle features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/*
  PriceOracleFullERC165.sol
  --------------------------
  - Manual or oracle-based price updates
  - Optional Chainlink integration
  - Human-readable + machine-readable price getters
  - ERC-165 interface detection (IPriceOracle)
*/

/// -----------------------------------------------------------------------
/// ERC-165 Interface
/// -----------------------------------------------------------------------
interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

/// -----------------------------------------------------------------------
/// Price Oracle Interface
/// -----------------------------------------------------------------------
interface IPriceOracle is IERC165 {
    function getPrice() external view returns (uint256 price, uint8 decimals, uint256 updatedAt);
    function getPriceString() external view returns (string memory);
}

/// -----------------------------------------------------------------------
/// Chainlink Aggregator Interface
/// -----------------------------------------------------------------------
interface AggregatorV3Interface {
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );
    function decimals() external view returns (uint8);
}

/// -----------------------------------------------------------------------
/// Main Contract
/// -----------------------------------------------------------------------
contract PriceOracleFullERC165 is IPriceOracle {
    address public owner;
    uint256 private _price;
    uint8 private _decimals;
    uint256 public lastUpdated;

    mapping(address => bool) public isOracle;

    event PriceUpdated(address indexed by, uint256 price, uint8 decimals, uint256 timestamp);
    event OracleAdded(address indexed oracle);
    event OracleRemoved(address indexed oracle);
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    modifier onlyOracle() {
        require(isOracle[msg.sender], "Not oracle");
        _;
    }

    constructor(uint256 initialPrice, uint8 initialDecimals) {
        owner = msg.sender;
        _setPrice(initialPrice, initialDecimals);
    }

    // ---------------- Owner + Oracle Management ----------------
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Zero address");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    function addOracle(address oracle) external onlyOwner {
        isOracle[oracle] = true;
        emit OracleAdded(oracle);
    }

    function removeOracle(address oracle) external onlyOwner {
        isOracle[oracle] = false;
        emit OracleRemoved(oracle);
    }

    // ---------------- Price Updates ----------------
    function setPrice(uint256 price, uint8 decimals) external onlyOwner {
        _setPrice(price, decimals);
    }

    function oracleSetPrice(uint256 price, uint8 decimals) external onlyOracle {
        _setPrice(price, decimals);
    }

    function updateFromChainlink(address aggregator) external onlyOwner {
        AggregatorV3Interface feed = AggregatorV3Interface(aggregator);
        (, int256 answer, , , ) = feed.latestRoundData();
        require(answer > 0, "Invalid feed answer");
        uint8 feedDecimals = feed.decimals();
        _setPrice(uint256(answer), feedDecimals);
    }

    function _setPrice(uint256 price, uint8 decimals) internal {
        require(price > 0, "Invalid price");
        _price = price;
        _decimals = decimals;
        lastUpdated = block.timestamp;
        emit PriceUpdated(msg.sender, price, decimals, block.timestamp);
    }

    // ---------------- Public View Functions ----------------
    /// Machine-readable version for wallets & explorers
    function getPrice() external view override returns (uint256 price, uint8 decimals, uint256 updatedAt) {
        return (_price, _decimals, lastUpdated);
    }

    /// Human-readable helper for UIs
    function getPriceString() external view override returns (string memory) {
        uint256 integerPart = _price / (10 ** _decimals);
        uint256 fractionalPart = _price % (10 ** _decimals);

        bytes memory fracStr = bytes(_uintToString(fractionalPart));
        uint8 missingZeros = _decimals > fracStr.length ? _decimals - uint8(fracStr.length) : 0;
        string memory paddedFraction = string(abi.encodePacked(_repeat("0", missingZeros), fracStr));

        return string(abi.encodePacked(_uintToString(integerPart), ".", paddedFraction, " USD"));
    }

    // ---------------- ERC-165 Interface Support ----------------
    function supportsInterface(bytes4 interfaceId) public pure virtual override returns (bool) {
        return
            interfaceId == type(IERC165).interfaceId ||   // 0x01ffc9a7
            interfaceId == type(IPriceOracle).interfaceId; // custom oracle interface
    }

    // ---------------- Internal Helpers ----------------
    function _uintToString(uint256 v) internal pure returns (string memory) {
        if (v == 0) return "0";
        uint256 len;
        uint256 j = v;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len;
        j = v;
        while (j != 0) {
            k--;
            bstr[k] = bytes1(uint8(48 + j % 10));
            j /= 10;
        }
        return string(bstr);
    }

    function _repeat(string memory s, uint8 n) internal pure returns (string memory) {
        bytes memory repeated;
        for (uint8 i = 0; i < n; i++) repeated = abi.encodePacked(repeated, s);
        return string(repeated);
    }
}

Tags:
ERC165, Oracle|addr:0x65dbddd8e75e135c4c374f552629ba795370188b|verified:true|block:23574208|tx:0xc3b15e0edcd6b6ad0d0a0a79780c102d1461f822e4c8a467f41bbd0324982070|first_check:1760434903

Submitted on: 2025-10-14 11:41:44

Comments

Log in to comment.

No comments yet.