ETH Price: $3,450.99 (-2.00%)
Gas: 3 Gwei

Contract

0x9bcE7eB7F44FCa5b97fbc668787990f1a7861DF6
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Report Expiry Pr...203413592024-07-19 15:04:594 days ago1721401499IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0011384814.4812075
Report Expiry Pr...203413582024-07-19 15:04:474 days ago1721401487IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0010397814.94862717
Report Expiry Pr...203413572024-07-19 15:04:354 days ago1721401475IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0011326814.40740954
Report Expiry Pr...203413562024-07-19 15:04:234 days ago1721401463IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0011473614.5941646
Report Expiry Pr...203413552024-07-19 15:04:114 days ago1721401451IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0011174214.23252772
Report Expiry Pr...203413542024-07-19 15:03:594 days ago1721401439IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0010285113.08245393
Report Expiry Pr...203374572024-07-19 2:01:475 days ago1721354507IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000617757.85769948
Report Expiry Pr...202911982024-07-12 15:04:1111 days ago1720796651IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000618037.57827661
Report Expiry Pr...202911972024-07-12 15:03:5911 days ago1720796639IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000550247.58807721
Report Expiry Pr...202911972024-07-12 15:03:5911 days ago1720796639IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000536516.82432922
Report Expiry Pr...202911962024-07-12 15:03:4711 days ago1720796627IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000490286.236252
Report Expiry Pr...202911962024-07-12 15:03:4711 days ago1720796627IN
0x9bcE7eB7...1a7861DF6
0 ETH0.00049336.27469274
Report Expiry Pr...202911942024-07-12 15:03:2311 days ago1720796603IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000625878.99807628
Report Expiry Pr...202911942024-07-12 15:03:2311 days ago1720796603IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000706568.99807628
Report Expiry Pr...202911932024-07-12 15:03:1111 days ago1720796591IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000664888.45716853
Report Expiry Pr...202911922024-07-12 15:02:5911 days ago1720796579IN
0x9bcE7eB7...1a7861DF6
0 ETH0.00068868.75890181
Set Aggregator202702462024-07-09 16:51:4714 days ago1720543907IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000454819.03103557
Report Expiry Pr...202410922024-07-05 15:06:3518 days ago1720191995IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0008039510.22603016
Report Expiry Pr...202410892024-07-05 15:05:5918 days ago1720191959IN
0x9bcE7eB7...1a7861DF6
0 ETH0.0007688610.604562
Report Expiry Pr...202410862024-07-05 15:05:2318 days ago1720191923IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000678968.64664984
Report Expiry Pr...202410832024-07-05 15:04:4718 days ago1720191887IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000725179.22398132
Report Expiry Pr...202410802024-07-05 15:04:1118 days ago1720191851IN
0x9bcE7eB7...1a7861DF6
0 ETH0.00065948.08674799
Report Expiry Pr...202410792024-07-05 15:03:5918 days ago1720191839IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000676268.60194924
Report Expiry Pr...202410782024-07-05 15:03:4718 days ago1720191827IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000717669.12850177
Report Expiry Pr...202410772024-07-05 15:03:3518 days ago1720191815IN
0x9bcE7eB7...1a7861DF6
0 ETH0.000717379.12482058
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
ChainlinkOracleDisputable

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 100000 runs

Other Settings:
default evmVersion
File 1 of 10 : ChainlinkOracleDisputable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {SafeCastLib} from "solmate/utils/SafeCastLib.sol";

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

// constants and types
import "./errors.sol";
import "../../config/constants.sol";

/**
 * @title ChainlinkOracleDisputable
 * @author antoncoding
 * @dev chainlink oracle that can be dispute by the owner
 */
contract ChainlinkOracleDisputable is ChainlinkOracle {
    using SafeCastLib for uint256;

    // base => quote => dispute period
    mapping(address => mapping(address => uint256)) public disputePeriod;

    /*///////////////////////////////////////////////////////////////
                                 Events
    //////////////////////////////////////////////////////////////*/

    event DisputePeriodUpdated(address base, address quote, uint256 period);

    /**
     * @dev return the maximum dispute period for the oracle
     */
    function maxDisputePeriod() external pure override returns (uint256) {
        return MAX_DISPUTE_PERIOD;
    }

    /**
     * @dev view function to check if dispute period is over
     */
    function isExpiryPriceFinalized(address _base, address _quote, uint256 _expiry) external view returns (bool) {
        return _isExpiryPriceFinalized(_base, _quote, _expiry);
    }

    /**
     * @dev dispute an reported expiry price from the owner. Cannot dispute an un-reported price
     * @param _base base asset
     * @param _quote quote asset
     * @param _expiry expiry timestamp
     * @param _newPrice new price to set
     */
    function disputePrice(address _base, address _quote, uint256 _expiry, uint256 _newPrice) external onlyOwner {
        ExpiryPrice memory entry = expiryPrices[_base][_quote][_expiry];
        if (entry.reportAt == 0) revert OC_PriceNotReported();

        if (entry.isDisputed) revert OC_PriceDisputed();

        if (entry.reportAt + disputePeriod[_base][_quote] < block.timestamp) revert OC_DisputePeriodOver();

        expiryPrices[_base][_quote][_expiry] = ExpiryPrice(true, uint64(block.timestamp), _newPrice.safeCastTo128());

        emit ExpiryPriceSet(_base, _quote, _expiry, _newPrice, true);
    }

    /**
     * @dev owner can set a price if the the price has not been pushed for at least 36 hours
     * @param _base base asset
     * @param _quote quote asset
     * @param _expiry expiry timestamp
     * @param _price price to set
     */
    function setExpiryPriceBackup(address _base, address _quote, uint256 _expiry, uint256 _price) external onlyOwner {
        ExpiryPrice memory entry = expiryPrices[_base][_quote][_expiry];
        if (entry.reportAt != 0) revert OC_PriceReported();

        if (_expiry + 36 hours > block.timestamp) revert OC_GracePeriodNotOver();

        expiryPrices[_base][_quote][_expiry] = ExpiryPrice(true, uint64(block.timestamp), _price.safeCastTo128());

        emit ExpiryPriceSet(_base, _quote, _expiry, _price, true);
    }

    /**
     * @dev set the dispute period for a specific base / quote asset
     * @param _base base asset
     * @param _quote quote asset
     * @param _period dispute period. Cannot be set to a value longer than 6 hours
     */
    function setDisputePeriod(address _base, address _quote, uint256 _period) external onlyOwner {
        if (_period > MAX_DISPUTE_PERIOD) revert OC_InvalidDisputePeriod();

        disputePeriod[_base][_quote] = _period;

        emit DisputePeriodUpdated(_base, _quote, _period);
    }

    /**
     * @dev overrides _isExpiryPriceFinalized() from ChainlinkOracle to check if dispute period is over
     *      if true, getPriceAtExpiry will return (price, true)
     */
    function _isExpiryPriceFinalized(address _base, address _quote, uint256 _expiry) internal view override returns (bool) {
        ExpiryPrice memory entry = expiryPrices[_base][_quote][_expiry];
        if (entry.reportAt == 0) return false;

        if (entry.isDisputed) return true;

        return block.timestamp > entry.reportAt + disputePeriod[_base][_quote];
    }
}

File 2 of 10 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 10 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 4 of 10 : FixedPointMathLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // Divide z by the denominator.
            z := div(z, denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        assembly {
            // Store x * y in z for now.
            z := mul(x, y)

            // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y))
            if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) {
                revert(0, 0)
            }

            // First, divide z - 1 by the denominator and add 1.
            // We allow z - 1 to underflow if z is 0, because we multiply the
            // end result by 0 if z is zero, ensuring we return 0 if z is zero.
            z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        assembly {
            // Start off with z at 1.
            z := 1

            // Used below to help find a nearby power of 2.
            let y := x

            // Find the lowest power of 2 that is at least sqrt(x).
            if iszero(lt(y, 0x100000000000000000000000000000000)) {
                y := shr(128, y) // Like dividing by 2 ** 128.
                z := shl(64, z) // Like multiplying by 2 ** 64.
            }
            if iszero(lt(y, 0x10000000000000000)) {
                y := shr(64, y) // Like dividing by 2 ** 64.
                z := shl(32, z) // Like multiplying by 2 ** 32.
            }
            if iszero(lt(y, 0x100000000)) {
                y := shr(32, y) // Like dividing by 2 ** 32.
                z := shl(16, z) // Like multiplying by 2 ** 16.
            }
            if iszero(lt(y, 0x10000)) {
                y := shr(16, y) // Like dividing by 2 ** 16.
                z := shl(8, z) // Like multiplying by 2 ** 8.
            }
            if iszero(lt(y, 0x100)) {
                y := shr(8, y) // Like dividing by 2 ** 8.
                z := shl(4, z) // Like multiplying by 2 ** 4.
            }
            if iszero(lt(y, 0x10)) {
                y := shr(4, y) // Like dividing by 2 ** 4.
                z := shl(2, z) // Like multiplying by 2 ** 2.
            }
            if iszero(lt(y, 0x8)) {
                // Equivalent to 2 ** z.
                z := shl(1, z)
            }

            // Shifting right by 1 is like dividing by 2.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // Compute a rounded down version of z.
            let zRoundDown := div(x, z)

            // If zRoundDown is smaller, use it.
            if lt(zRoundDown, z) {
                z := zRoundDown
            }
        }
    }
}

File 5 of 10 : SafeCastLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Safe unsigned integer casting library that reverts on overflow.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)
library SafeCastLib {
    function safeCastTo248(uint256 x) internal pure returns (uint248 y) {
        require(x < 1 << 248);

        y = uint248(x);
    }

    function safeCastTo224(uint256 x) internal pure returns (uint224 y) {
        require(x < 1 << 224);

        y = uint224(x);
    }

    function safeCastTo192(uint256 x) internal pure returns (uint192 y) {
        require(x < 1 << 192);

        y = uint192(x);
    }

    function safeCastTo160(uint256 x) internal pure returns (uint160 y) {
        require(x < 1 << 160);

        y = uint160(x);
    }

    function safeCastTo128(uint256 x) internal pure returns (uint128 y) {
        require(x < 1 << 128);

        y = uint128(x);
    }

    function safeCastTo96(uint256 x) internal pure returns (uint96 y) {
        require(x < 1 << 96);

        y = uint96(x);
    }

    function safeCastTo64(uint256 x) internal pure returns (uint64 y) {
        require(x < 1 << 64);

        y = uint64(x);
    }

    function safeCastTo32(uint256 x) internal pure returns (uint32 y) {
        require(x < 1 << 32);

        y = uint32(x);
    }

    function safeCastTo8(uint256 x) internal pure returns (uint8 y) {
        require(x < 1 << 8);

        y = uint8(x);
    }
}

File 6 of 10 : constants.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

///@dev unit used for option amount and strike prices
uint8 constant UNIT_DECIMALS = 6;

///@dev unit scaled used to convert amounts.
uint256 constant UNIT = 10 ** 6;

///@dev int scaled used to convert amounts.
int256 constant sUNIT = int256(10 ** 6);

///@dev basis point for 100%.
uint256 constant BPS = 10000;

///@dev maximum dispute period for oracle
uint256 constant MAX_DISPUTE_PERIOD = 6 hours;

File 7 of 10 : ChainlinkOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Ownable} from "openzeppelin/access/Ownable.sol";
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
import {SafeCastLib} from "solmate/utils/SafeCastLib.sol";

// interfaces
import {IOracle} from "../../interfaces/IOracle.sol";
import {IAggregatorV3} from "../../interfaces/IAggregatorV3.sol";

// constants and types
import "./errors.sol";
import "../../config/constants.sol";

/**
 * @title ChainlinkOracle
 * @author @antoncoding
 * @dev return base / quote price, with 6 decimals
 */
contract ChainlinkOracle is IOracle, Ownable {
    using FixedPointMathLib for uint256;
    using SafeCastLib for uint256;

    struct ExpiryPrice {
        bool isDisputed;
        uint64 reportAt;
        uint128 price;
    }

    struct AggregatorData {
        address addr;
        uint8 decimals;
        uint32 maxDelay;
        bool isStable; // answer of stable asset can be used as long as the answer is not stale
    }

    ///@dev base => quote => expiry => price.
    mapping(address => mapping(address => mapping(uint256 => ExpiryPrice))) public expiryPrices;

    // asset => aggregator
    mapping(address => AggregatorData) public aggregators;

    /*///////////////////////////////////////////////////////////////
                                 Events
    //////////////////////////////////////////////////////////////*/

    event ExpiryPriceSet(address base, address quote, uint256 expiry, uint256 price, bool isDispute);

    /*///////////////////////////////////////////////////////////////
                            External Functions
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice  get spot price of _base, denominated in _quote.
     * @param _base base asset. for ETH/USD price, ETH is the base asset
     * @param _quote quote asset. for ETH/USD price, USD is the quote asset
     * @return price with 6 decimals
     */
    function getSpotPrice(address _base, address _quote) external view returns (uint256) {
        (uint256 basePrice, uint8 baseDecimals) = _getSpotPriceFromAggregator(_base);
        (uint256 quotePrice, uint8 quoteDecimals) = _getSpotPriceFromAggregator(_quote);
        return _toPriceWithUnitDecimals(basePrice, quotePrice, baseDecimals, quoteDecimals);
    }

    /**
     * @dev get expiry price of underlying, denominated in strike asset.
     *         can revert if expiry is in the future, or the price has not been reported by authorized party
     * @param _base base asset. for ETH/USD price, ETH is the base asset
     * @param _quote quote asset. for ETH/USD price, USD is the quote asset
     * @param _expiry expiry timestamp
     * @return price with 6 decimals
     */
    function getPriceAtExpiry(address _base, address _quote, uint256 _expiry)
        external
        view
        returns (uint256 price, bool isFinalized)
    {
        ExpiryPrice memory data = expiryPrices[_base][_quote][_expiry];
        if (data.reportAt == 0) revert OC_PriceNotReported();

        return (data.price, _isExpiryPriceFinalized(_base, _quote, _expiry));
    }

    /**
     * @dev return the maximum dispute period for the oracle
     * @dev this oracle has no dispute mechanism, as long as a price is reported, it can be used to settle.
     */
    function maxDisputePeriod() external view virtual returns (uint256) {
        return 0;
    }

    /**
     * @notice report expiry price and write to storage
     * @dev anyone can call this function and freeze the expiry price
     */
    function reportExpiryPrice(address _base, address _quote, uint256 _expiry, uint80 _baseRoundId, uint80 _quoteRoundId)
        external
    {
        if (_expiry > block.timestamp) revert OC_CannotReportForFuture();
        if (expiryPrices[_base][_quote][_expiry].reportAt != 0) revert OC_PriceReported();

        (uint256 basePrice, uint8 baseDecimals) = _getLastPriceBeforeExpiry(_base, _baseRoundId, _expiry);
        (uint256 quotePrice, uint8 quoteDecimals) = _getLastPriceBeforeExpiry(_quote, _quoteRoundId, _expiry);
        uint256 price = _toPriceWithUnitDecimals(basePrice, quotePrice, baseDecimals, quoteDecimals);

        expiryPrices[_base][_quote][_expiry] = ExpiryPrice(false, uint64(block.timestamp), price.safeCastTo128());

        emit ExpiryPriceSet(_base, _quote, _expiry, price, false);
    }

    /*///////////////////////////////////////////////////////////////
                            Admin Functions
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev admin function to set aggregator address for an asset
     */
    function setAggregator(address _asset, address _aggregator, uint32 _maxDelay, bool _isStable) external onlyOwner {
        uint8 decimals = IAggregatorV3(_aggregator).decimals();
        aggregators[_asset] = AggregatorData(_aggregator, decimals, _maxDelay, _isStable);
    }

    /*///////////////////////////////////////////////////////////////
                            Internal functions
    //////////////////////////////////////////////////////////////*/

    /**
     * @dev this oracle has no dispute mechanism, so always return true.
     *      a un-reported price should have reverted at this point.
     */
    function _isExpiryPriceFinalized(address, address, uint256) internal view virtual returns (bool) {
        return true;
    }

    /**
     * @notice  convert prices from aggregator of base & quote asset to base / quote, denominated in UNIT
     * @param _basePrice price of base asset from aggregator
     * @param _quotePrice price of quote asset from aggregator
     * @param _baseDecimals decimals of _basePrice
     * @param _quoteDecimals decimals of _quotePrice
     * @return price base / quote price with {UNIT_DECIMALS} decimals
     */
    function _toPriceWithUnitDecimals(uint256 _basePrice, uint256 _quotePrice, uint8 _baseDecimals, uint8 _quoteDecimals)
        internal
        pure
        returns (uint256 price)
    {
        if (_baseDecimals == _quoteDecimals) {
            // .mul UNIT to make sure the final price has 6 decimals
            price = _basePrice.mulDivUp(UNIT, _quotePrice);
        } else {
            // we will return basePrice * 10^(baseMulDecimals) / quotePrice;
            int8 baseMulDecimals = int8(UNIT_DECIMALS) + int8(_quoteDecimals) - int8(_baseDecimals);
            if (baseMulDecimals > 0) {
                price = _basePrice.mulDivUp(10 ** uint8(baseMulDecimals), _quotePrice);
            } else {
                price = _basePrice / (_quotePrice * (10 ** uint8(-baseMulDecimals)));
            }
        }
    }

    /**
     * @dev fetch price with their native decimals from Chainlink aggregator
     */
    function _getSpotPriceFromAggregator(address _asset) internal view returns (uint256 price, uint8 decimals) {
        AggregatorData memory aggregator = aggregators[_asset];
        if (aggregator.addr == address(0)) revert CL_AggregatorNotSet();

        // request answer from Chainlink
        (, int256 answer,, uint256 updatedAt,) = IAggregatorV3(address(aggregator.addr)).latestRoundData();

        if (block.timestamp - updatedAt > aggregator.maxDelay) revert CL_StaleAnswer();

        return (uint256(answer), aggregator.decimals);
    }

    /**
     * @notice get the price from an roundId, and make sure it is the last price before expiry
     * @param _asset asset to report
     * @param _roundId chainlink roundId that should be used
     * @param _expiry expiry timestamp to report
     */
    function _getLastPriceBeforeExpiry(address _asset, uint80 _roundId, uint256 _expiry)
        internal
        view
        returns (uint256 price, uint8 decimals)
    {
        AggregatorData memory aggregator = aggregators[_asset];
        if (aggregator.addr == address(0)) revert CL_AggregatorNotSet();

        // request answer from Chainlink
        (, int256 answer,, uint256 updatedAt,) = IAggregatorV3(address(aggregator.addr)).getRoundData(_roundId);

        // if expiry < updatedAt, this line will revert
        if (_expiry - updatedAt > aggregator.maxDelay) revert CL_StaleAnswer();

        // it is not a stable asset: make sure timestamp of answer #(round + 1) is higher than expiry
        if (!aggregator.isStable) {
            (,,, uint256 nextRoundUpdatedAt,) = IAggregatorV3(address(aggregator.addr)).getRoundData(_roundId + 1);
            if (nextRoundUpdatedAt <= _expiry) revert CL_RoundIdTooSmall();
        }

        return (uint256(answer), aggregator.decimals);
    }
}

File 8 of 10 : errors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

error OC_CannotReportForFuture();

error OC_PriceNotReported();

error OC_PriceReported();

///@dev cannot dispute the settlement price after dispute period is over
error OC_DisputePeriodOver();

///@dev cannot force-set an settlement price until grace period is passed and no one has set the price.
error OC_GracePeriodNotOver();

///@dev already disputed
error OC_PriceDisputed();

///@dev owner trying to set a dispute period that is invalid
error OC_InvalidDisputePeriod();

// Chainlink oracle

error CL_AggregatorNotSet();

error CL_StaleAnswer();

error CL_RoundIdTooSmall();

File 9 of 10 : IAggregatorV3.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IAggregatorV3 {
    function decimals() external view returns (uint8);

    function description() external view returns (string memory);

    function version() external view returns (uint256);

    // getRoundData and latestRoundData should both raise "No data present"
    // if they do not have data to report, instead of returning unset values
    // which could be misinterpreted as actual reported values.
    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);
}

File 10 of 10 : IOracle.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IOracle {
    /**
     * @notice  get spot price of _base, denominated in _quote.
     * @param _base base asset. for ETH/USD price, ETH is the base asset
     * @param _quote quote asset. for ETH/USD price, USD is the quote asset
     * @return price with 6 decimals
     */
    function getSpotPrice(address _base, address _quote) external view returns (uint256);

    /**
     * @dev get expiry price of underlying, denominated in strike asset.
     * @param _base base asset. for ETH/USD price, ETH is the base asset
     * @param _quote quote asset. for ETH/USD price, USD is the quote asset
     * @param _expiry expiry timestamp
     *
     * @return price with 6 decimals
     */
    function getPriceAtExpiry(address _base, address _quote, uint256 _expiry)
        external
        view
        returns (uint256 price, bool isFinalized);

    /**
     * @dev return the maximum dispute period for the oracle
     * @dev this will only be checked during oracle registration, as a soft constraint on integrating oracles.
     */
    function maxDisputePeriod() external view returns (uint256 disputePeriod);
}

Settings
{
  "remappings": [
    "array-lib/=lib/array-lib/src/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
    "openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 100000
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {
    "src/core/engines/cross-margin/CrossMarginLib.sol": {
      "CrossMarginLib": "0x6c3e422630711498920303fbc1255044b98cb006"
    },
    "src/core/engines/cross-margin/CrossMarginMath.sol": {
      "CrossMarginMath": "0x62142797d4c5465bd6839d9275d43c694e29622c"
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"name":"CL_AggregatorNotSet","type":"error"},{"inputs":[],"name":"CL_RoundIdTooSmall","type":"error"},{"inputs":[],"name":"CL_StaleAnswer","type":"error"},{"inputs":[],"name":"OC_CannotReportForFuture","type":"error"},{"inputs":[],"name":"OC_DisputePeriodOver","type":"error"},{"inputs":[],"name":"OC_GracePeriodNotOver","type":"error"},{"inputs":[],"name":"OC_InvalidDisputePeriod","type":"error"},{"inputs":[],"name":"OC_PriceDisputed","type":"error"},{"inputs":[],"name":"OC_PriceNotReported","type":"error"},{"inputs":[],"name":"OC_PriceReported","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"base","type":"address"},{"indexed":false,"internalType":"address","name":"quote","type":"address"},{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"DisputePeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"base","type":"address"},{"indexed":false,"internalType":"address","name":"quote","type":"address"},{"indexed":false,"internalType":"uint256","name":"expiry","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isDispute","type":"bool"}],"name":"ExpiryPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"aggregators","outputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint32","name":"maxDelay","type":"uint32"},{"internalType":"bool","name":"isStable","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"disputePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"},{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"disputePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"expiryPrices","outputs":[{"internalType":"bool","name":"isDisputed","type":"bool"},{"internalType":"uint64","name":"reportAt","type":"uint64"},{"internalType":"uint128","name":"price","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"getPriceAtExpiry","outputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"isFinalized","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"}],"name":"getSpotPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"}],"name":"isExpiryPriceFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxDisputePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"},{"internalType":"uint80","name":"_baseRoundId","type":"uint80"},{"internalType":"uint80","name":"_quoteRoundId","type":"uint80"}],"name":"reportExpiryPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_aggregator","type":"address"},{"internalType":"uint32","name":"_maxDelay","type":"uint32"},{"internalType":"bool","name":"_isStable","type":"bool"}],"name":"setAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"setDisputePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_base","type":"address"},{"internalType":"address","name":"_quote","type":"address"},{"internalType":"uint256","name":"_expiry","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"name":"setExpiryPriceBackup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611bb98061007e6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a611610097578063edb1cd6311610066578063edb1cd6314610378578063f20268981461038b578063f2fde38b14610393578063f84255bf146103a657600080fd5b8063715018a6146102805780638da5cb5b14610288578063c2d7794c146102b0578063dcae9973146102db57600080fd5b806317e0310e116100d357806317e0310e146102225780633c52586a146102375780635261ae4f1461025a57806365f381fb1461026d57600080fd5b8063112cdab9146100fa578063157a1448146101d957806315e84af914610201575b600080fd5b61018e6101083660046116ac565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169060ff74010000000000000000000000000000000000000000820481169163ffffffff7501000000000000000000000000000000000000000000820416917901000000000000000000000000000000000000000000000000009091041684565b6040805173ffffffffffffffffffffffffffffffffffffffff909516855260ff909316602085015263ffffffff90911691830191909152151560608201526080015b60405180910390f35b6101ec6101e73660046116c7565b6103b9565b604080519283529015156020830152016101d0565b61021461020f366004611703565b6104af565b6040519081526020016101d0565b610235610230366004611736565b6104ea565b005b61024a6102453660046116c7565b610775565b60405190151581526020016101d0565b610235610268366004611790565b61078c565b61023561027b366004611736565b610a24565b610235610bac565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6102146102be366004611703565b600360209081526000928352604080842090915290825290205481565b6103406102e93660046116c7565b600160209081526000938452604080852082529284528284209052825290205460ff811690610100810467ffffffffffffffff1690690100000000000000000090046fffffffffffffffffffffffffffffffff1683565b60408051931515845267ffffffffffffffff90921660208401526fffffffffffffffffffffffffffffffff16908201526060016101d0565b6102356103863660046117f4565b610bc0565b615460610214565b6102356103a13660046116ac565b610d76565b6102356103b43660046116c7565b610e32565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292815282822084835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff169381019390935290918291820361047e576040517fed94154600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806040015161048e878787610ef2565b6fffffffffffffffffffffffffffffffff9091169350915050935093915050565b60008060006104bd85610ff7565b915091506000806104cd86610ff7565b915091506104dd848385846111b8565b9450505050505b92915050565b6104f2611254565b73ffffffffffffffffffffffffffffffffffffffff848116600090815260016020908152604080832093871683529281528282208583528152908290208251606081018452905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252156105b3576040517fc1d7baf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426105c1846201fa40611889565b11156105f9576040517f2684dd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516060810182526001815267ffffffffffffffff42166020820152908101610623846112d5565b6fffffffffffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff8781166000818152600160208181526040808420958c168085529582528084208b85528252928390208751815489840151998601519098166901000000000000000000027fffffffffffffff00000000000000000000000000000000ffffffffffffffffff67ffffffffffffffff909a16610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909916989098171797909716959095179095558051918252928101919091529081018590526060810184905260808101919091527f0544c84da3680da5acad8d30edbf557014ced588781a8c10918da78a77cae7199060a00160405180910390a15050505050565b6000610782848484610ef2565b90505b9392505050565b428311156107c6576040517f59dfb79f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8581166000908152600160209081526040808320938816835292815282822086835290522054610100900467ffffffffffffffff1615610847576040517fc1d7baf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806108558785876112f8565b915091506000806108678886896112f8565b915091506000610879858486856111b8565b604080516060810182526000815267ffffffffffffffff4216602082015291925081016108a5836112d5565b6fffffffffffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff808d166000908152600160209081526040808320938f1683529281528282208d835281528282208551815492870151968501519095166901000000000000000000027fffffffffffffff00000000000000000000000000000000ffffffffffffffffff67ffffffffffffffff909716610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff961515969096167fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000090931692909217949094179490941693909317909155517f0544c84da3680da5acad8d30edbf557014ced588781a8c10918da78a77cae71991610a10918d918d918d91879173ffffffffffffffffffffffffffffffffffffffff958616815293909416602084015260408301919091526060820152901515608082015260a00190565b60405180910390a150505050505050505050565b610a2c611254565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600160209081526040808320938716835292815282822085835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff16938101939093529003610aed576040517fed94154600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805115610b26576040517fb203764400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600360209081526040808320938816835292815291902054908201514291610b749167ffffffffffffffff16611889565b10156105f9576040517f0615424500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bb4611254565b610bbe60006115e0565b565b610bc8611254565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c39919061189c565b6040805160808101825273ffffffffffffffffffffffffffffffffffffffff968716815260ff928316602080830191825263ffffffff978816838501908152961515606084019081529989166000908152600290915292909220905181549251955198511515790100000000000000000000000000000000000000000000000000027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff99909716750100000000000000000000000000000000000000000002989098167fffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffff9590931674010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909216979096169690961795909517919091169390931717905550565b610d7e611254565b73ffffffffffffffffffffffffffffffffffffffff8116610e26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610e2f816115e0565b50565b610e3a611254565b615460811115610e76576040517f547835d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905581519283528201929092529081018290527fab3eda2c63a44ea5b348b46c4ddca5d21c512b1f39d283599b851ca75c5934e49060600160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292815282822084835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff16938101939093529091908203610f8e576000915050610785565b805115610f9f576001915050610785565b73ffffffffffffffffffffffffffffffffffffffff808616600090815260036020908152604080832093881683529281529190205490820151610fec919067ffffffffffffffff16611889565b421195945050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526002602090815260408083208151608081018352905494851680825260ff74010000000000000000000000000000000000000000870481169483019490945263ffffffff75010000000000000000000000000000000000000000008704169282019290925279010000000000000000000000000000000000000000000000000090940490911615156060840152909182916110db576040517fcb100cb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080826000015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561112d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115191906118bf565b50935050925050826040015163ffffffff16814261116f9190611909565b11156111a7576040517f2c6d489400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506020909101519094909350915050565b60008160ff168360ff16036111dc576111d585620f424086611655565b905061124c565b6000836111ea84600661191c565b6111f4919061195b565b905060008160000b131561121f5761121861121082600a611aba565b879087611655565b915061124a565b61122881611ac9565b61123390600a611aba565b61123d9086611b07565b6112479087611b1e565b91505b505b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610bbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e1d565b600070010000000000000000000000000000000082106112f457600080fd5b5090565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526002602090815260408083208151608081018352905494851680825260ff74010000000000000000000000000000000000000000870481169483019490945263ffffffff75010000000000000000000000000000000000000000008704169282019290925279010000000000000000000000000000000000000000000000000090940490911615156060840152909182916113dc576040517fcb100cb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516040517f9a6fc8f500000000000000000000000000000000000000000000000000000000815269ffffffffffffffffffff87166004820152600091829173ffffffffffffffffffffffffffffffffffffffff90911690639a6fc8f59060240160a060405180830381865afa15801561145a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147e91906118bf565b50935050925050826040015163ffffffff16818761149c9190611909565b11156114d4576040517f2c6d489400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001516115cc57825160009073ffffffffffffffffffffffffffffffffffffffff16639a6fc8f56115088a6001611b59565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815269ffffffffffffffffffff909116600482015260240160a060405180830381865afa158015611567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158b91906118bf565b5093505050508681116115ca576040517f10b2547e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b506020909101519092509050935093915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b82820281151584158583048514171661166d57600080fd5b6001826001830304018115150290509392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146116a757600080fd5b919050565b6000602082840312156116be57600080fd5b61078582611683565b6000806000606084860312156116dc57600080fd5b6116e584611683565b92506116f360208501611683565b9150604084013590509250925092565b6000806040838503121561171657600080fd5b61171f83611683565b915061172d60208401611683565b90509250929050565b6000806000806080858703121561174c57600080fd5b61175585611683565b935061176360208601611683565b93969395505050506040820135916060013590565b69ffffffffffffffffffff81168114610e2f57600080fd5b600080600080600060a086880312156117a857600080fd5b6117b186611683565b94506117bf60208701611683565b93506040860135925060608601356117d681611778565b915060808601356117e681611778565b809150509295509295909350565b6000806000806080858703121561180a57600080fd5b61181385611683565b935061182160208601611683565b9250604085013563ffffffff8116811461183a57600080fd5b91506060850135801515811461184f57600080fd5b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104e4576104e461185a565b6000602082840312156118ae57600080fd5b815160ff8116811461078557600080fd5b600080600080600060a086880312156118d757600080fd5b85516118e281611778565b8095505060208601519350604086015192506060860151915060808601516117e681611778565b818103818111156104e4576104e461185a565b600081810b9083900b01607f81137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80821217156104e4576104e461185a565b600082810b9082900b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808112607f821317156104e4576104e461185a565b600181815b808511156119f357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119d9576119d961185a565b808516156119e657918102915b93841c939080029061199f565b509250929050565b600082611a0a575060016104e4565b81611a17575060006104e4565b8160018114611a2d5760028114611a3757611a53565b60019150506104e4565b60ff841115611a4857611a4861185a565b50506001821b6104e4565b5060208310610133831016604e8410600b8410161715611a76575081810a6104e4565b611a80838361199a565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611ab257611ab261185a565b029392505050565b600061078560ff8416836119fb565b60008160000b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808103611afe57611afe61185a565b60000392915050565b80820281158282048414176104e4576104e461185a565b600082611b54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b69ffffffffffffffffffff818116838216019080821115611b7c57611b7c61185a565b509291505056fea2646970667358221220e86fd5f619baf292f88805e51df25f0776268eea05087cec21da855c2ba7a20764736f6c63430008110033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a611610097578063edb1cd6311610066578063edb1cd6314610378578063f20268981461038b578063f2fde38b14610393578063f84255bf146103a657600080fd5b8063715018a6146102805780638da5cb5b14610288578063c2d7794c146102b0578063dcae9973146102db57600080fd5b806317e0310e116100d357806317e0310e146102225780633c52586a146102375780635261ae4f1461025a57806365f381fb1461026d57600080fd5b8063112cdab9146100fa578063157a1448146101d957806315e84af914610201575b600080fd5b61018e6101083660046116ac565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169060ff74010000000000000000000000000000000000000000820481169163ffffffff7501000000000000000000000000000000000000000000820416917901000000000000000000000000000000000000000000000000009091041684565b6040805173ffffffffffffffffffffffffffffffffffffffff909516855260ff909316602085015263ffffffff90911691830191909152151560608201526080015b60405180910390f35b6101ec6101e73660046116c7565b6103b9565b604080519283529015156020830152016101d0565b61021461020f366004611703565b6104af565b6040519081526020016101d0565b610235610230366004611736565b6104ea565b005b61024a6102453660046116c7565b610775565b60405190151581526020016101d0565b610235610268366004611790565b61078c565b61023561027b366004611736565b610a24565b610235610bac565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6102146102be366004611703565b600360209081526000928352604080842090915290825290205481565b6103406102e93660046116c7565b600160209081526000938452604080852082529284528284209052825290205460ff811690610100810467ffffffffffffffff1690690100000000000000000090046fffffffffffffffffffffffffffffffff1683565b60408051931515845267ffffffffffffffff90921660208401526fffffffffffffffffffffffffffffffff16908201526060016101d0565b6102356103863660046117f4565b610bc0565b615460610214565b6102356103a13660046116ac565b610d76565b6102356103b43660046116c7565b610e32565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292815282822084835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff169381019390935290918291820361047e576040517fed94154600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806040015161048e878787610ef2565b6fffffffffffffffffffffffffffffffff9091169350915050935093915050565b60008060006104bd85610ff7565b915091506000806104cd86610ff7565b915091506104dd848385846111b8565b9450505050505b92915050565b6104f2611254565b73ffffffffffffffffffffffffffffffffffffffff848116600090815260016020908152604080832093871683529281528282208583528152908290208251606081018452905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff1692810192909252156105b3576040517fc1d7baf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b426105c1846201fa40611889565b11156105f9576040517f2684dd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516060810182526001815267ffffffffffffffff42166020820152908101610623846112d5565b6fffffffffffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff8781166000818152600160208181526040808420958c168085529582528084208b85528252928390208751815489840151998601519098166901000000000000000000027fffffffffffffff00000000000000000000000000000000ffffffffffffffffff67ffffffffffffffff909a16610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffff000000000000000000909916989098171797909716959095179095558051918252928101919091529081018590526060810184905260808101919091527f0544c84da3680da5acad8d30edbf557014ced588781a8c10918da78a77cae7199060a00160405180910390a15050505050565b6000610782848484610ef2565b90505b9392505050565b428311156107c6576040517f59dfb79f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8581166000908152600160209081526040808320938816835292815282822086835290522054610100900467ffffffffffffffff1615610847576040517fc1d7baf100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806108558785876112f8565b915091506000806108678886896112f8565b915091506000610879858486856111b8565b604080516060810182526000815267ffffffffffffffff4216602082015291925081016108a5836112d5565b6fffffffffffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff808d166000908152600160209081526040808320938f1683529281528282208d835281528282208551815492870151968501519095166901000000000000000000027fffffffffffffff00000000000000000000000000000000ffffffffffffffffff67ffffffffffffffff909716610100027fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff961515969096167fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000090931692909217949094179490941693909317909155517f0544c84da3680da5acad8d30edbf557014ced588781a8c10918da78a77cae71991610a10918d918d918d91879173ffffffffffffffffffffffffffffffffffffffff958616815293909416602084015260408301919091526060820152901515608082015260a00190565b60405180910390a150505050505050505050565b610a2c611254565b73ffffffffffffffffffffffffffffffffffffffff8481166000908152600160209081526040808320938716835292815282822085835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff16938101939093529003610aed576040517fed94154600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805115610b26576040517fb203764400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8086166000908152600360209081526040808320938816835292815291902054908201514291610b749167ffffffffffffffff16611889565b10156105f9576040517f0615424500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610bb4611254565b610bbe60006115e0565b565b610bc8611254565b60008373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c39919061189c565b6040805160808101825273ffffffffffffffffffffffffffffffffffffffff968716815260ff928316602080830191825263ffffffff978816838501908152961515606084019081529989166000908152600290915292909220905181549251955198511515790100000000000000000000000000000000000000000000000000027fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff99909716750100000000000000000000000000000000000000000002989098167fffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffffff9590931674010000000000000000000000000000000000000000027fffffffffffffffffffffff000000000000000000000000000000000000000000909216979096169690961795909517919091169390931717905550565b610d7e611254565b73ffffffffffffffffffffffffffffffffffffffff8116610e26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610e2f816115e0565b50565b610e3a611254565b615460811115610e76576040517f547835d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905581519283528201929092529081018290527fab3eda2c63a44ea5b348b46c4ddca5d21c512b1f39d283599b851ca75c5934e49060600160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292815282822084835281528282208351606081018552905460ff811615158252610100810467ffffffffffffffff16928201839052690100000000000000000090046fffffffffffffffffffffffffffffffff16938101939093529091908203610f8e576000915050610785565b805115610f9f576001915050610785565b73ffffffffffffffffffffffffffffffffffffffff808616600090815260036020908152604080832093881683529281529190205490820151610fec919067ffffffffffffffff16611889565b421195945050505050565b73ffffffffffffffffffffffffffffffffffffffff80821660009081526002602090815260408083208151608081018352905494851680825260ff74010000000000000000000000000000000000000000870481169483019490945263ffffffff75010000000000000000000000000000000000000000008704169282019290925279010000000000000000000000000000000000000000000000000090940490911615156060840152909182916110db576040517fcb100cb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080826000015173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561112d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115191906118bf565b50935050925050826040015163ffffffff16814261116f9190611909565b11156111a7576040517f2c6d489400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506020909101519094909350915050565b60008160ff168360ff16036111dc576111d585620f424086611655565b905061124c565b6000836111ea84600661191c565b6111f4919061195b565b905060008160000b131561121f5761121861121082600a611aba565b879087611655565b915061124a565b61122881611ac9565b61123390600a611aba565b61123d9086611b07565b6112479087611b1e565b91505b505b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610bbe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e1d565b600070010000000000000000000000000000000082106112f457600080fd5b5090565b73ffffffffffffffffffffffffffffffffffffffff80841660009081526002602090815260408083208151608081018352905494851680825260ff74010000000000000000000000000000000000000000870481169483019490945263ffffffff75010000000000000000000000000000000000000000008704169282019290925279010000000000000000000000000000000000000000000000000090940490911615156060840152909182916113dc576040517fcb100cb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80516040517f9a6fc8f500000000000000000000000000000000000000000000000000000000815269ffffffffffffffffffff87166004820152600091829173ffffffffffffffffffffffffffffffffffffffff90911690639a6fc8f59060240160a060405180830381865afa15801561145a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147e91906118bf565b50935050925050826040015163ffffffff16818761149c9190611909565b11156114d4576040517f2c6d489400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82606001516115cc57825160009073ffffffffffffffffffffffffffffffffffffffff16639a6fc8f56115088a6001611b59565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815269ffffffffffffffffffff909116600482015260240160a060405180830381865afa158015611567573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158b91906118bf565b5093505050508681116115ca576040517f10b2547e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b506020909101519092509050935093915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b82820281151584158583048514171661166d57600080fd5b6001826001830304018115150290509392505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146116a757600080fd5b919050565b6000602082840312156116be57600080fd5b61078582611683565b6000806000606084860312156116dc57600080fd5b6116e584611683565b92506116f360208501611683565b9150604084013590509250925092565b6000806040838503121561171657600080fd5b61171f83611683565b915061172d60208401611683565b90509250929050565b6000806000806080858703121561174c57600080fd5b61175585611683565b935061176360208601611683565b93969395505050506040820135916060013590565b69ffffffffffffffffffff81168114610e2f57600080fd5b600080600080600060a086880312156117a857600080fd5b6117b186611683565b94506117bf60208701611683565b93506040860135925060608601356117d681611778565b915060808601356117e681611778565b809150509295509295909350565b6000806000806080858703121561180a57600080fd5b61181385611683565b935061182160208601611683565b9250604085013563ffffffff8116811461183a57600080fd5b91506060850135801515811461184f57600080fd5b939692955090935050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104e4576104e461185a565b6000602082840312156118ae57600080fd5b815160ff8116811461078557600080fd5b600080600080600060a086880312156118d757600080fd5b85516118e281611778565b8095505060208601519350604086015192506060860151915060808601516117e681611778565b818103818111156104e4576104e461185a565b600081810b9083900b01607f81137fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80821217156104e4576104e461185a565b600082810b9082900b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808112607f821317156104e4576104e461185a565b600181815b808511156119f357817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156119d9576119d961185a565b808516156119e657918102915b93841c939080029061199f565b509250929050565b600082611a0a575060016104e4565b81611a17575060006104e4565b8160018114611a2d5760028114611a3757611a53565b60019150506104e4565b60ff841115611a4857611a4861185a565b50506001821b6104e4565b5060208310610133831016604e8410600b8410161715611a76575081810a6104e4565b611a80838361199a565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611ab257611ab261185a565b029392505050565b600061078560ff8416836119fb565b60008160000b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808103611afe57611afe61185a565b60000392915050565b80820281158282048414176104e4576104e461185a565b600082611b54577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b69ffffffffffffffffffff818116838216019080821115611b7c57611b7c61185a565b509291505056fea2646970667358221220e86fd5f619baf292f88805e51df25f0776268eea05087cec21da855c2ba7a20764736f6c63430008110033

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ 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.