ETH Price: $2,044.02 (-3.65%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Ojo PT Fe...245183832026-02-23 8:25:5937 days ago1771835159IN
0x6dB4264f...a97c77567
0 ETH0.000009580.04439991
Create Ojo PT Fe...243833182026-02-04 11:53:4756 days ago1770206027IN
0x6dB4264f...a97c77567
0 ETH0.00003210.14876641
Create Ojo PT Fe...243190502026-01-26 12:37:3565 days ago1769431055IN
0x6dB4264f...a97c77567
0 ETH0.000025790.11951337
Create Ojo PT Fe...243136342026-01-25 18:30:3566 days ago1769365835IN
0x6dB4264f...a97c77567
0 ETH0.000029560.12692266
Create Ojo PT Fe...243134892026-01-25 18:01:3566 days ago1769364095IN
0x6dB4264f...a97c77567
0 ETH0.000017690.12386964
Create Ojo PT Fe...243039582026-01-24 10:08:2367 days ago1769249303IN
0x6dB4264f...a97c77567
0 ETH0.000010480.07496856
Create Ojo PT Fe...220631882025-03-17 1:01:11381 days ago1742173271IN
0x6dB4264f...a97c77567
0 ETH0.000219740.94513884

Latest 16 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
From
To
0x3d602d80245183832026-02-23 8:25:5937 days ago1771835159
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80243833182026-02-04 11:53:4756 days ago1770206027
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80243190502026-01-26 12:37:3565 days ago1769431055
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80243136342026-01-25 18:30:3566 days ago1769365835
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80243134892026-01-25 18:01:3566 days ago1769364095
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80243039582026-01-24 10:08:2367 days ago1769249303
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80236716662025-10-27 22:10:35156 days ago1761603035
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80236716662025-10-27 22:10:35156 days ago1761603035
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80232429742025-08-28 23:43:47216 days ago1756424627
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80228456712025-07-04 11:51:35271 days ago1751629895
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80224340792025-05-07 20:23:47329 days ago1746649427
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80224339632025-05-07 19:59:59329 days ago1746647999
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80224265502025-05-06 18:47:47330 days ago1746557267
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80222884362025-04-17 11:32:11349 days ago1744889531
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x3d602d80220631882025-03-17 1:01:11381 days ago1742173271
0x6dB4264f...a97c77567
 Contract Creation0 ETH
0x60808060220630762025-03-17 0:38:35381 days ago1742171915
0x6dB4264f...a97c77567
 Contract Creation0 ETH
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OjoPTFeedFactory

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.22;

import "@openzeppelin/contracts/proxy/Clones.sol";
import "./OjoPTFeed.sol";

contract OjoPTFeedFactory {
    using Clones for address;

    address public immutable implementation;
    mapping(address => address) public OjoPTFeedAddresses;

    event OjoPTFeedCreated(address indexed feed);

    constructor() {
        implementation = address(new OjoPTFeed());
    }

    function createOjoPTFeed(address FEED_1, address FEED_2) external returns (address FEED) {
        FEED = implementation.clone();
        OjoPTFeed(FEED).initialize(FEED_1, FEED_2);
        OjoPTFeedAddresses[msg.sender] = FEED;
        emit OjoPTFeedCreated(FEED);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/Clones.sol)

pragma solidity ^0.8.20;

import {Create2} from "../utils/Create2.sol";
import {Errors} from "../utils/Errors.sol";

/**
 * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for
 * deploying minimal proxy contracts, also known as "clones".
 *
 * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
 * > a minimal bytecode implementation that delegates all calls to a known, fixed address.
 *
 * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
 * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
 * deterministic method.
 */
library Clones {
    error CloneArgumentsTooLong();

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create opcode, which should never revert.
     */
    function clone(address implementation) internal returns (address instance) {
        return clone(implementation, 0);
    }

    /**
     * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency
     * to the new contract.
     *
     * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
     * to always have enough balance for new deployments. Consider exposing this function under a payable method.
     */
    function clone(address implementation, uint256 value) internal returns (address instance) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        assembly ("memory-safe") {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create(value, 0x09, 0x37)
        }
        if (instance == address(0)) {
            revert Errors.FailedDeployment();
        }
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy
     * the clone. Using the same `implementation` and `salt` multiple times will revert, since
     * the clones cannot be deployed twice at the same address.
     */
    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
        return cloneDeterministic(implementation, salt, 0);
    }

    /**
     * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with
     * a `value` parameter to send native currency to the new contract.
     *
     * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
     * to always have enough balance for new deployments. Consider exposing this function under a payable method.
     */
    function cloneDeterministic(
        address implementation,
        bytes32 salt,
        uint256 value
    ) internal returns (address instance) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        assembly ("memory-safe") {
            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes
            // of the `implementation` address with the bytecode before the address.
            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.
            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))
            instance := create2(value, 0x09, 0x37, salt)
        }
        if (instance == address(0)) {
            revert Errors.FailedDeployment();
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        assembly ("memory-safe") {
            let ptr := mload(0x40)
            mstore(add(ptr, 0x38), deployer)
            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
            mstore(add(ptr, 0x14), implementation)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
            mstore(add(ptr, 0x58), salt)
            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
            predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff)
        }
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
     */
    function predictDeterministicAddress(
        address implementation,
        bytes32 salt
    ) internal view returns (address predicted) {
        return predictDeterministicAddress(implementation, salt, address(this));
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
     * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
     * access the arguments within the implementation, use {fetchCloneArgs}.
     *
     * This function uses the create opcode, which should never revert.
     */
    function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) {
        return cloneWithImmutableArgs(implementation, args, 0);
    }

    /**
     * @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value`
     * parameter to send native currency to the new contract.
     *
     * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
     * to always have enough balance for new deployments. Consider exposing this function under a payable method.
     */
    function cloneWithImmutableArgs(
        address implementation,
        bytes memory args,
        uint256 value
    ) internal returns (address instance) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
        assembly ("memory-safe") {
            instance := create(value, add(bytecode, 0x20), mload(bytecode))
        }
        if (instance == address(0)) {
            revert Errors.FailedDeployment();
        }
    }

    /**
     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation` with custom
     * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
     * access the arguments within the implementation, use {fetchCloneArgs}.
     *
     * This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same
     * `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice
     * at the same address.
     */
    function cloneDeterministicWithImmutableArgs(
        address implementation,
        bytes memory args,
        bytes32 salt
    ) internal returns (address instance) {
        return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0);
    }

    /**
     * @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs],
     * but with a `value` parameter to send native currency to the new contract.
     *
     * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory)
     * to always have enough balance for new deployments. Consider exposing this function under a payable method.
     */
    function cloneDeterministicWithImmutableArgs(
        address implementation,
        bytes memory args,
        bytes32 salt,
        uint256 value
    ) internal returns (address instance) {
        bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
        return Create2.deploy(value, salt, bytecode);
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
     */
    function predictDeterministicAddressWithImmutableArgs(
        address implementation,
        bytes memory args,
        bytes32 salt,
        address deployer
    ) internal pure returns (address predicted) {
        bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args);
        return Create2.computeAddress(salt, keccak256(bytecode), deployer);
    }

    /**
     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}.
     */
    function predictDeterministicAddressWithImmutableArgs(
        address implementation,
        bytes memory args,
        bytes32 salt
    ) internal view returns (address predicted) {
        return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this));
    }

    /**
     * @dev Get the immutable args attached to a clone.
     *
     * - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this
     *   function will return an empty array.
     * - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or
     *   `cloneDeterministicWithImmutableArgs`, this function will return the args array used at
     *   creation.
     * - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This
     *   function should only be used to check addresses that are known to be clones.
     */
    function fetchCloneArgs(address instance) internal view returns (bytes memory) {
        bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short
        assembly ("memory-safe") {
            extcodecopy(instance, add(result, 32), 45, mload(result))
        }
        return result;
    }

    /**
     * @dev Helper that prepares the initcode of the proxy with immutable args.
     *
     * An assembly variant of this function requires copying the `args` array, which can be efficiently done using
     * `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using
     * abi.encodePacked is more expensive but also more portable and easier to review.
     *
     * NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes.
     * With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes.
     */
    function _cloneCodeWithImmutableArgs(
        address implementation,
        bytes memory args
    ) private pure returns (bytes memory) {
        if (args.length > 24531) revert CloneArgumentsTooLong();
        return
            abi.encodePacked(
                hex"61",
                uint16(args.length + 45),
                hex"3d81600a3d39f3363d3d373d3d3d363d73",
                implementation,
                hex"5af43d82803e903d91602b57fd5bf3",
                args
            );
    }
}

// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.22;

import {AggregatorV3Interface} from "./interfaces/AggregatorV2V3Interface.sol";
import {AggregatorV2V3Interface} from "./interfaces/AggregatorV2V3Interface.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";

contract OjoPTFeed is AggregatorV3Interface, Initializable {
    uint256 constant DEFAULT_VERSION = 1;
    uint256 public constant STALENESS_THRESHOLD = 24 hours;

    AggregatorV2V3Interface public FEED_1;
    AggregatorV2V3Interface public FEED_2;
    string private feedDescription;

    error GetRoundDataCanBeOnlyCalledWithLatestRound(uint80 requestedRoundId);
    error StaleOracleData(uint256 timestamp, uint256 threshold);

    function initialize(address _FEED_1, address _FEED_2) external initializer {
        require(_FEED_1 != address(0), "Zero address for FEED_1");
        require(_FEED_2 != address(0), "Zero address for FEED_2");

        AggregatorV2V3Interface feed1 = AggregatorV2V3Interface(_FEED_1);
        AggregatorV2V3Interface feed2 = AggregatorV2V3Interface(_FEED_2);

        require(feed1.decimals() == feed2.decimals(), "FEED_1 decimals not equal to FEED_2 decimals");

        FEED_1 = feed1;
        FEED_2 = feed2;
        feedDescription = string(abi.encodePacked("Ojo PT Feed ", feed1.description()));
    }

    function decimals() external view override returns (uint8) {
        return FEED_1.decimals();
    }

    function description() external view override returns (string memory) {
        return feedDescription;
    }

    function version() external view override returns (uint256) {
        return DEFAULT_VERSION;
    }

    /**
     * @notice Returns data for a specific round ID
     * @dev Note: This function returns the roundId from whichever oracle provided the minimum price.
     * This means roundIds may not be monotonically increasing when switching between oracles,
     * which could break protocols that rely on roundId being non-decreasing.
     */
    function getRoundData(
        uint80 _roundId
    )
        external
        view
        override
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
    {
        (roundId, answer, startedAt, updatedAt, answeredInRound) = latestRoundData();
        if (_roundId != roundId) {
            revert GetRoundDataCanBeOnlyCalledWithLatestRound(_roundId);
        }
        return (roundId, answer, startedAt, updatedAt, answeredInRound);
    }

    /**
     * @notice Returns the latest round data
     * @dev Note: This function returns the roundId from whichever oracle provided the minimum price.
     * This means roundIds may not be monotonically increasing when switching between oracles,
     * which could break protocols that rely on roundId being non-decreasing.
     */
    function latestRoundData()
        public
        view
        override
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
    {
        (uint80 roundId1, int256 answer1, uint256 startedAt1, uint256 updatedAt1, uint80 answeredInRound1) =
            FEED_1.latestRoundData();

        (uint80 roundId2, int256 answer2, uint256 startedAt2, uint256 updatedAt2, uint80 answeredInRound2) =
            FEED_2.latestRoundData();

        if (updatedAt1 != 0 && block.timestamp - updatedAt1 > STALENESS_THRESHOLD) {
            revert StaleOracleData(updatedAt1, STALENESS_THRESHOLD);
        }

        if (updatedAt2 != 0 && block.timestamp - updatedAt2 > STALENESS_THRESHOLD) {
            revert StaleOracleData(updatedAt2, STALENESS_THRESHOLD);
        }

        if (answer1 <= answer2) {
            return (roundId1, answer1, startedAt1, updatedAt1, answeredInRound1);
        } else {
            return (roundId2, answer2, startedAt2, updatedAt2, answeredInRound2);
        }
    }

    function getActiveOracle() external view returns (address) {
        (, int256 answer1,,,) = FEED_1.latestRoundData();
        (, int256 answer2,,,) = FEED_2.latestRoundData();

        if (answer1 <= answer2) {
            return address(FEED_1);
        } else {
            return address(FEED_2);
        }
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
 * `CREATE2` can be used to compute in advance the address where a smart
 * contract will be deployed, which allows for interesting new mechanisms known
 * as 'counterfactual interactions'.
 *
 * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
 * information.
 */
library Create2 {
    /**
     * @dev There's no code to deploy.
     */
    error Create2EmptyBytecode();

    /**
     * @dev Deploys a contract using `CREATE2`. The address where the contract
     * will be deployed can be known in advance via {computeAddress}.
     *
     * The bytecode for a contract can be obtained from Solidity with
     * `type(contractName).creationCode`.
     *
     * Requirements:
     *
     * - `bytecode` must not be empty.
     * - `salt` must have not been used for `bytecode` already.
     * - the factory must have a balance of at least `amount`.
     * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.
     */
    function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }
        if (bytecode.length == 0) {
            revert Create2EmptyBytecode();
        }
        assembly ("memory-safe") {
            addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
            // if no address was created, and returndata is not empty, bubble revert
            if and(iszero(addr), not(iszero(returndatasize()))) {
                let p := mload(0x40)
                returndatacopy(p, 0, returndatasize())
                revert(p, returndatasize())
            }
        }
        if (addr == address(0)) {
            revert Errors.FailedDeployment();
        }
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the
     * `bytecodeHash` or `salt` will result in a new destination address.
     */
    function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
        return computeAddress(salt, bytecodeHash, address(this));
    }

    /**
     * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at
     * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.
     */
    function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
        assembly ("memory-safe") {
            let ptr := mload(0x40) // Get free memory pointer

            // |                   | ↓ ptr ...  ↓ ptr + 0x0B (start) ...  ↓ ptr + 0x20 ...  ↓ ptr + 0x40 ...   |
            // |-------------------|---------------------------------------------------------------------------|
            // | bytecodeHash      |                                                        CCCCCCCCCCCCC...CC |
            // | salt              |                                      BBBBBBBBBBBBB...BB                   |
            // | deployer          | 000000...0000AAAAAAAAAAAAAAAAAAA...AA                                     |
            // | 0xFF              |            FF                                                             |
            // |-------------------|---------------------------------------------------------------------------|
            // | memory            | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC |
            // | keccak(start, 85) |            ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ |

            mstore(add(ptr, 0x40), bytecodeHash)
            mstore(add(ptr, 0x20), salt)
            mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes
            let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff
            mstore8(start, 0xff)
            addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff)
        }
    }
}

File 5 of 7 : Errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

interface AggregatorInterface {
    function latestAnswer() external view returns (int256);
    function latestTimestamp() external view returns (uint256);
    function latestRound() external view returns (uint256);
    function getAnswer(
        uint256 roundId
    ) external view returns (int256);
    function getTimestamp(
        uint256 roundId
    ) external view returns (uint256);

    event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
    event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}

interface AggregatorV3Interface {
    function decimals() external view returns (uint8);
    function description() external view returns (string memory);
    function version() external view returns (uint256);

    function getRoundData(
        uint80 _roundId
    )
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
    function latestRoundData()
        external
        view
        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}

interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}

Settings
{
  "remappings": [
    "forge-std/=lib/forge-std/src/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"feed","type":"address"}],"name":"OjoPTFeedCreated","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"OjoPTFeedAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"FEED_1","type":"address"},{"internalType":"address","name":"FEED_2","type":"address"}],"name":"createOjoPTFeed","outputs":[{"internalType":"address","name":"FEED","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60a0806040523461007c57610c838181016001600160401b038111838210176100685782916102f8833903905ff0801561005d576001600160a01b03166080526040516102779081610081823960805181818160bf01526101fc0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fdfe608060408181526004361015610013575f80fd5b5f915f3560e01c9081635c60da1b146101ea57508063d117eccb1461007c5763d1d698e114610040575f80fd5b34610078576020366003190112610078576020916001600160a01b039082908261006861022b565b1681528085522054169051908152f35b5080fd5b5090346101d557816003193601126101d55761009661022b565b6001600160a01b0390602435828116908190036101d5576e5af43d82803e903d91602b57fd5bf37f0000000000000000000000000000000000000000000000000000000000000000763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b1760205282603760095ff0169283156101d957833b156101d557855163485cc95560e01b81529216600483015260248201525f8160448183865af180156101cb57610199575b50807f26b9b4af2e39ec1b98baf623b9b23b57f0385d52216304f5f3def7a55609e51a602094338552848652808520836bffffffffffffffffffffffff60a01b825416179055519380a28152f35b92915067ffffffffffffffff83116101b757918152905f908061014b565b634e487b7160e01b5f52604160045260245ffd5b84513d5f823e3d90fd5b5f80fd5b855163b06ebf3d60e01b8152600490fd5b346101d5575f3660031901126101d5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600435906001600160a01b03821682036101d55756fea264697066735822122054311f45b79b722553da85d549086dd24243ce99d48dd97175a6739b1c528e0464736f6c634300081600336080806040523461001657610c68908161001b8239f35b5f80fdfe6080604090808252600480361015610015575f80fd5b5f3560e01c918263313ce567146108545750816341299f941461082c578163485cc9551461030457816354fd4d50146102e95781637215b0bf146102cc5781637284e416146101d157816372b14462146101a45781639a6fc8f51461011157508063d84bd024146100ea5763feaf968c1461008e575f80fd5b346100e6575f3660031901126100e6576100e2906100aa610aae565b945169ffffffffffffffffffff94851681526020810193909352604083019190915260608201529116608082015290819060a0820190565b0390f35b5f80fd5b50346100e6575f3660031901126100e6575f5490516001600160a01b039091168152602090f35b9050346100e65760203660031901126100e65780359069ffffffffffffffffffff908183168093036100e657610145610aae565b949192969093958616810361018e575050945169ffffffffffffffffffff938416815260208101949094526040840194909452606083019390935291909116608082015260a090f35b87516322bfd6df60e01b81529182015260249150fd5b82346100e6575f3660031901126100e6576020906101c06109c1565b90516001600160a01b039091168152f35b82346100e6575f3660031901126100e6578051905f916002546101f38161093d565b808352826020958692838301946001906001811690815f146102ad5750600114610250575b5050610226925003836108ee565b61024283519485938185525192838092860152858501906108cd565b601f01601f19168101030190f35b9093915060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace935f915b81831061029557508894505082010161022688610218565b8554888401850152948501948794509183019161027d565b91505061022694925060ff19168552151560051b820101869288610218565b82346100e6575f3660031901126100e65760209051620151808152f35b82346100e6575f3660031901126100e6576020905160018152f35b82346100e657806003193601126100e6576001600160a01b038235818116939192908490036100e657602480359384168094036100e6577ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009485549360ff85851c16159267ffffffffffffffff9283871696871580610825575b6001809914908161081b575b159081610812575b506108025767ffffffffffffffff19811688178a55856107e3575b5080156107a157871561075f57855163313ce56760e01b80825260209991908a828781875afa918215610736575f92610740575b5088519081528a818781865afa9081156107365760ff9182915f91610709575b50169116036106b25783915f916bffffffffffffffffffffffff60a01b82818554161784558a5416178955875194858092633942720b60e11b82525afa9283156106a8575f93610620575b5061048d602c875180956b027b53790282a102332b2b2160a51b8c83015261047d8c825192839186860191016108cd565b810103600c8101865201846108ee565b825193841161060f57505081906104a560025461093d565b601f81116105a0575b508690601f8311600114610521575f92610516575b50505f19600383901b1c191690841b176002555b6104dd57005b7fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29368ff000000000000000019815416905551908152a1005b0151905087806104c3565b90869350601f1983169160025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace925f5b8a82821061058a5750508411610572575b505050811b016002556104d7565b01515f1960f88460031b161c19169055878080610564565b8385015186558a97909501949384019301610553565b90915060025f527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace601f840160051c810191888510610605575b84939291601f89920160051c01915b8281106105f75750506104ae565b5f81558594508891016105e9565b90915081906105da565b604190634e487b7160e01b5f52525ffd5b9092503d805f833e61063281836108ee565b81019088818303126100e6578051908582116100e6570181601f820112156100e657805185811161069657875192610673601f8301601f19168c01856108ee565b8184528a82840101116100e65761068f918a80850191016108cd565b918961044c565b83604186634e487b7160e01b5f52525ffd5b86513d5f823e3d90fd5b865162461bcd60e51b81528085018a9052602c818501527f464545445f3120646563696d616c73206e6f7420657175616c20746f2046454560448201526b445f3220646563696d616c7360a01b6064820152608490fd5b61072991508d803d1061072f575b61072181836108ee565b810190610924565b8e610401565b503d610717565b89513d5f823e3d90fd5b6107589192508b3d8d1161072f5761072181836108ee565b908c6103e1565b855162461bcd60e51b81526020818501526017818401527f5a65726f206164647265737320666f7220464545445f320000000000000000006044820152606490fd5b855162461bcd60e51b81526020818501526017818401527f5a65726f206164647265737320666f7220464545445f310000000000000000006044820152606490fd5b68ffffffffffffffffff191668010000000000000001178955896103ad565b865163f92ee8a960e01b81528490fd5b9050158b610392565b303b15915061038a565b508561037e565b82346100e6575f3660031901126100e65760015490516001600160a01b039091168152602090f35b9150346100e6575f3660031901126100e6575f5463313ce56760e01b8352602091839182906001600160a01b03165afa9081156108c357916020925f926108a1575b5060ff905191168152f35b60ff9192506108bc90843d861161072f5761072181836108ee565b9190610896565b82513d5f823e3d90fd5b5f5b8381106108de5750505f910152565b81810151838201526020016108cf565b90601f8019910116810190811067ffffffffffffffff82111761091057604052565b634e487b7160e01b5f52604160045260245ffd5b908160209103126100e6575160ff811681036100e65790565b90600182811c9216801561096b575b602083101461095757565b634e487b7160e01b5f52602260045260245ffd5b91607f169161094c565b519069ffffffffffffffffffff821682036100e657565b908160a09103126100e6576109a081610975565b916020820151916040810151916109be608060608401519301610975565b90565b5f54604051633fabe5a360e21b8082526001600160a01b0392831692909160a0918282600481885afa918215610a5e575f92610a69575b5060015416926040519081528281600481875afa928315610a5e575f93610a2a575b505013610a25575090565b905090565b610a4a929350803d10610a57575b610a4281836108ee565b81019061098c565b5050509050905f80610a1a565b503d610a38565b6040513d5f823e3d90fd5b610a81919250833d8511610a5757610a4281836108ee565b5050509050905f6109f8565b91908203918211610a9a57565b634e487b7160e01b5f52601160045260245ffd5b60018060a01b03805f541660408051938492633fabe5a360e21b9081855284600460a09889935afa928315610c29575f915f975f975f975f97610bf2575b5081906001541692600485518095819382525afa8015610be8575f80945f945f945f94610bbd575b505089151580610ba8575b610b885783151580610b73575b610b535750848b13610b445750505050509493929190565b99509297509095509350919050565b51635f51811b60e11b815260048101849052620151806024820152604490fd5b5062015180610b828542610a8d565b11610b2c565b51635f51811b60e11b8152600481018a9052620151806024820152604490fd5b5062015180610bb78b42610a8d565b11610b1f565b93509350945050610bda9250803d10610a5757610a4281836108ee565b929491939092915f80610b14565b83513d5f823e3d90fd5b9299509550809750610c149296508093503d8411610a5757610a4281836108ee565b97939992949199989098949998979690610aec565b513d5f823e3d90fdfea26469706673582212207ef3530a3a8bbb281a55c2023c13d4b560902b508907f8832b0218445a9a45dd64736f6c63430008160033

Deployed Bytecode

0x608060408181526004361015610013575f80fd5b5f915f3560e01c9081635c60da1b146101ea57508063d117eccb1461007c5763d1d698e114610040575f80fd5b34610078576020366003190112610078576020916001600160a01b039082908261006861022b565b1681528085522054169051908152f35b5080fd5b5090346101d557816003193601126101d55761009661022b565b6001600160a01b0390602435828116908190036101d5576e5af43d82803e903d91602b57fd5bf37f0000000000000000000000005aab95e3c6f9ba0ccfa0a17c2c7235633c7c6585763d602d80600a3d3981f3363d3d373d3d3d363d7300000062ffffff8260881c16175f5260781b1760205282603760095ff0169283156101d957833b156101d557855163485cc95560e01b81529216600483015260248201525f8160448183865af180156101cb57610199575b50807f26b9b4af2e39ec1b98baf623b9b23b57f0385d52216304f5f3def7a55609e51a602094338552848652808520836bffffffffffffffffffffffff60a01b825416179055519380a28152f35b92915067ffffffffffffffff83116101b757918152905f908061014b565b634e487b7160e01b5f52604160045260245ffd5b84513d5f823e3d90fd5b5f80fd5b855163b06ebf3d60e01b8152600490fd5b346101d5575f3660031901126101d5577f0000000000000000000000005aab95e3c6f9ba0ccfa0a17c2c7235633c7c65856001600160a01b03168152602090f35b600435906001600160a01b03821682036101d55756fea264697066735822122054311f45b79b722553da85d549086dd24243ce99d48dd97175a6739b1c528e0464736f6c63430008160033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.