ETH Price: $3,388.37 (+4.46%)
Gas: 0.3 Gwei

Contract

0x3bf1D588Bd17127934421Ebfcfa6482ACA85FdC8
 

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
Update YUSD Pric...237365282025-11-06 0:00:111 hr ago1762387211IN
0x3bf1D588...ACA85FdC8
0 ETH0.000007670.23766108
Update YUSD Pric...237341452025-11-05 16:00:119 hrs ago1762358411IN
0x3bf1D588...ACA85FdC8
0 ETH0.000040711.26055852
Update YUSD Pric...237317692025-11-05 8:00:3517 hrs ago1762329635IN
0x3bf1D588...ACA85FdC8
0 ETH0.000010740.33274794
Update YUSD Pric...237293912025-11-05 0:00:4725 hrs ago1762300847IN
0x3bf1D588...ACA85FdC8
0 ETH0.000029570.91549574
Update YUSD Pric...237270072025-11-04 16:00:3533 hrs ago1762272035IN
0x3bf1D588...ACA85FdC8
0 ETH0.000060121.8613099
Update YUSD Pric...237246292025-11-04 8:00:4741 hrs ago1762243247IN
0x3bf1D588...ACA85FdC8
0 ETH0.000026010.80535573
Update YUSD Pric...237222382025-11-04 0:00:352 days ago1762214435IN
0x3bf1D588...ACA85FdC8
0 ETH0.000007080.21931699
Update YUSD Pric...237198542025-11-03 16:00:232 days ago1762185623IN
0x3bf1D588...ACA85FdC8
0 ETH0.0003508110.86050211
Update YUSD Pric...237174632025-11-03 8:00:112 days ago1762156811IN
0x3bf1D588...ACA85FdC8
0 ETH0.000003980.12338432
Update YUSD Pric...237150822025-11-03 0:00:473 days ago1762128047IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002930.09077888
Update YUSD Pric...237126942025-11-02 16:00:113 days ago1762099211IN
0x3bf1D588...ACA85FdC8
0 ETH0.000007640.23681667
Update YUSD Pric...237103082025-11-02 8:00:113 days ago1762070411IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002580.07993162
Update YUSD Pric...237079202025-11-02 0:00:114 days ago1762041611IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002250.06981489
Update YUSD Pric...237055452025-11-01 16:00:474 days ago1762012847IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002890.08976542
Update YUSD Pric...237031572025-11-01 8:00:354 days ago1761984035IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002940.09104247
Update YUSD Pric...237007672025-11-01 0:00:115 days ago1761955211IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002590.08032538
Update YUSD Pric...236983902025-10-31 16:00:115 days ago1761926411IN
0x3bf1D588...ACA85FdC8
0 ETH0.000019620.60757368
Update YUSD Pric...236960072025-10-31 8:00:235 days ago1761897623IN
0x3bf1D588...ACA85FdC8
0 ETH0.000003290.10215
Update YUSD Pric...236936302025-10-31 0:00:236 days ago1761868823IN
0x3bf1D588...ACA85FdC8
0 ETH0.00000330.10220428
Update YUSD Pric...236912542025-10-30 16:00:356 days ago1761840035IN
0x3bf1D588...ACA85FdC8
0 ETH0.000029280.90649952
Update YUSD Pric...236888682025-10-30 8:00:356 days ago1761811235IN
0x3bf1D588...ACA85FdC8
0 ETH0.000004380.13575463
Update YUSD Pric...236864892025-10-30 0:00:237 days ago1761782423IN
0x3bf1D588...ACA85FdC8
0 ETH0.000004650.14418936
Update YUSD Pric...236841022025-10-29 16:00:117 days ago1761753611IN
0x3bf1D588...ACA85FdC8
0 ETH0.000024250.75076953
Update YUSD Pric...236817272025-10-29 8:01:117 days ago1761724871IN
0x3bf1D588...ACA85FdC8
0 ETH0.000003170.09823452
Update YUSD Pric...236793422025-10-29 0:00:358 days ago1761696035IN
0x3bf1D588...ACA85FdC8
0 ETH0.000002940.09101953
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
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:
AegisChainlinkOracleV2

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "@openzeppelin/contracts/access/Ownable2Step.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";

// Импорты интерфейсов для Morpho ChainlinkOracle V2
import { IOracle } from "./interfaces/IOracle.sol";
import { AggregatorV3Interface } from "./interfaces/AggregatorV3Interface.sol";
import { IERC4626 } from "./interfaces/IERC4626.sol";
import { IMorphoChainlinkOracleV2 } from "./interfaces/IMorphoChainlinkOracleV2.sol";

/// @title AegisChainlinkOracleV2
/// @notice Aegis Oracle with manual price updates for Morpho Blue compatibility
/// @dev YUSD is a stablecoin pegged to 1 USD. Uses operator-set prices only (no Chainlink feeds)
contract AegisChainlinkOracleV2 is Ownable2Step, IMorphoChainlinkOracleV2 {
  using Math for uint256;

  struct YUSDUSDPriceData {
    int256 price;
    uint32 timestamp;
  }

  YUSDUSDPriceData private _priceData;
  mapping(address => bool) private _operators;

  /* IMMUTABLES - Required by IMorphoChainlinkOracleV2 */

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we work with ERC-20 tokens, not ERC4626 vaults
  IERC4626 public immutable BASE_VAULT;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to 1 as required when vault is address(0)
  uint256 public immutable BASE_VAULT_CONVERSION_SAMPLE;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we work with ERC-20 tokens, not ERC4626 vaults
  IERC4626 public immutable QUOTE_VAULT;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to 1 as required when vault is address(0)
  uint256 public immutable QUOTE_VAULT_CONVERSION_SAMPLE;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we use manual price updates only
  AggregatorV3Interface public immutable BASE_FEED_1;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we use manual price updates only
  AggregatorV3Interface public immutable BASE_FEED_2;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we use manual price updates only
  AggregatorV3Interface public immutable QUOTE_FEED_1;

  /// @inheritdoc IMorphoChainlinkOracleV2
  /// @dev Set to address(0) since we use manual price updates only
  AggregatorV3Interface public immutable QUOTE_FEED_2;

  /// @inheritdoc IMorphoChainlinkOracleV2
  uint256 public immutable SCALE_FACTOR;



  event UpdateYUSDPrice(int256 price, uint32 timestamp);
  event SetOperator(address indexed operator, bool allowed);

  error ZeroAddress();
  error AccessForbidden();

  modifier onlyOperator() {
    if (!_operators[_msgSender()]) {
      revert AccessForbidden();
    }
    _;
  }

  constructor(
    address[] memory operators,
    address initialOwner
  ) Ownable(initialOwner) {
    if (initialOwner == address(0)) revert ZeroAddress();

    // Initialize immutable variables for Morpho compatibility
    // No ERC4626 vaults - set to zero address
    BASE_VAULT = IERC4626(address(0));
    BASE_VAULT_CONVERSION_SAMPLE = 1; // Required to be 1 when vault is zero address
    QUOTE_VAULT = IERC4626(address(0));
    QUOTE_VAULT_CONVERSION_SAMPLE = 1; // Required to be 1 when vault is zero address
    
    // All Chainlink feeds set to zero address (not used)
    BASE_FEED_1 = AggregatorV3Interface(address(0));
    BASE_FEED_2 = AggregatorV3Interface(address(0));
    QUOTE_FEED_1 = AggregatorV3Interface(address(0));
    QUOTE_FEED_2 = AggregatorV3Interface(address(0));



    // Calculate scale factor for price conversion
    // For YUSD (8 decimals) to 1e36 format: scale = 1e28
    SCALE_FACTOR = 10 ** (36 - 8); // = 1e28

    // Set operators
    for (uint256 i = 0; i < operators.length; i++) {
      _setOperator(operators[i], true);
    }
  }

  function decimals() public pure returns (uint8) {
    return 8;
  }

  /// @dev Returns current YUSD/USD price
  function yusdUSDPrice() public view returns (int256) {
    return _priceData.price;
  }

  /// @dev Returns timestamp of last price update
  function lastUpdateTimestamp() public view returns (uint32) {
    return _priceData.timestamp;
  }

  /**
   * @dev Updates YUSD/USD price.
   * @dev Price should have 8 decimals
   */
  function updateYUSDPrice(int256 newPrice) external onlyOperator {
    _priceData.price = newPrice;
    _priceData.timestamp = uint32(block.timestamp);
    emit UpdateYUSDPrice(_priceData.price, _priceData.timestamp);
  }

  /// @dev Adds/removes operator
  function setOperator(address operator, bool allowed) external onlyOwner {
    _setOperator(operator, allowed);
  }



  function _setOperator(address operator, bool allowed) internal {
    _operators[operator] = allowed;
    emit SetOperator(operator, allowed);
  }



  /// @inheritdoc IOracle
  /// @notice Returns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36
  /// @dev For YUSD stablecoin, uses operator-set price only (manual mode)
  function price() external view returns (uint256) {
    if (_priceData.price <= 0) {
      // Default to 1 USD if no price set
      return 1e36;
    }
    
    // Scale from 8 decimals to 1e36 format using SCALE_FACTOR
    return uint256(_priceData.price) * SCALE_FACTOR;
  }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.20;

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

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is specified at deployment time in the constructor for `Ownable`. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

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

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

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        if (pendingOwner() != sender) {
            revert OwnableUnauthorizedAccount(sender);
        }
        _transferOwnership(sender);
    }
}

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

pragma solidity ^0.8.20;

/**
 * @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;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

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

pragma solidity ^0.8.20;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Muldiv operation overflow.
     */
    error MathOverflowedMulDiv();

    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            return a / b;
        }

        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            if (denominator <= prod1) {
                revert MathOverflowedMulDiv();
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

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

/// @dev From
/// https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol
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);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

interface IERC4626 {
  function convertToAssets(uint256) external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

import { IERC4626 } from "./IERC4626.sol";
import { IOracle } from "./IOracle.sol";
import { AggregatorV3Interface } from "./AggregatorV3Interface.sol";

/// @title IMorphoChainlinkOracleV2
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Interface of MorphoChainlinkOracleV2.
interface IMorphoChainlinkOracleV2 is IOracle {
  /// @notice Returns the address of the base ERC4626 vault.
  function BASE_VAULT() external view returns (IERC4626);

  /// @notice Returns the base vault conversion sample.
  function BASE_VAULT_CONVERSION_SAMPLE() external view returns (uint256);

  /// @notice Returns the address of the quote ERC4626 vault.
  function QUOTE_VAULT() external view returns (IERC4626);

  /// @notice Returns the quote vault conversion sample.
  function QUOTE_VAULT_CONVERSION_SAMPLE() external view returns (uint256);

  /// @notice Returns the address of the first base feed.
  function BASE_FEED_1() external view returns (AggregatorV3Interface);

  /// @notice Returns the address of the second base feed.
  function BASE_FEED_2() external view returns (AggregatorV3Interface);

  /// @notice Returns the address of the first quote feed.
  function QUOTE_FEED_1() external view returns (AggregatorV3Interface);

  /// @notice Returns the address of the second quote feed.
  function QUOTE_FEED_2() external view returns (AggregatorV3Interface);

  /// @notice Returns the price scale factor, calculated at contract creation.
  function SCALE_FACTOR() external view returns (uint256);
}

File 9 of 9 : IOracle.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title IOracle
/// @author Morpho Labs
/// @custom:contact [email protected]
/// @notice Interface that oracles used by Morpho must implement.
/// @dev It is the user's responsibility to select markets with safe oracles.
interface IOracle {
    /// @notice Returns the price of 1 asset of collateral token quoted in 1 asset of loan token, scaled by 1e36.
    /// @dev It corresponds to the price of 10**(collateral token decimals) assets of collateral token quoted in
    /// 10**(loan token decimals) assets of loan token with `36 + loan token decimals - collateral token decimals`
    /// decimals of precision.
    function price() external view returns (uint256);
}

Settings
{
  "viaIR": true,
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "none"
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address[]","name":"operators","type":"address[]"},{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessForbidden","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"SetOperator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int256","name":"price","type":"int256"},{"indexed":false,"internalType":"uint32","name":"timestamp","type":"uint32"}],"name":"UpdateYUSDPrice","type":"event"},{"inputs":[],"name":"BASE_FEED_1","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_FEED_2","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_VAULT","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_VAULT_CONVERSION_SAMPLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_FEED_1","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_FEED_2","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_VAULT","outputs":[{"internalType":"contract IERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_VAULT_CONVERSION_SAMPLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"lastUpdateTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"setOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"newPrice","type":"int256"}],"name":"updateYUSDPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"yusdUSDPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]

6101a06040523461022e576109ac8038038061001a81610249565b92833981019060408183031261022e5780516001600160401b03811161022e5781019180601f8401121561022e578251926001600160401b038411610233578360051b9060208061006c818501610249565b80978152019282010192831161022e57602001905b82821061021657506001600160a01b03926100a19250602001905061026e565b16801561020057600180546001600160a01b031990811690915560008054918216831781556001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3600080608052600160a0528060c052600160e05280610100528061012052806101405280610160526b204fce5e3e2502611000000061018052805b825181101561019457600190818060a01b0360208260051b86010151168084526004602052604084208360ff198254161790557f1618a22a3b00b9ac70fd5a82f1f5cdd8cb272bd0f1b740ddf7c26ab05881dd5b6020604051858152a201610131565b60405161072990816102838239608051816101cf015260a05181610649015260c051816105de015260e05181610589015261010051816101110152610120518161023d015261014051816104c3015261016051816102bd01526101805181818161028401526106ab0152f35b631e4fbdf760e01b600052600060045260246000fd5b602080916102238461026e565b815201910190610081565b600080fd5b634e487b7160e01b600052604160045260246000fd5b6040519190601f01601f191682016001600160401b0381118382101761023357604052565b51906001600160a01b038216820361022e5756fe608080604052600436101561001357600080fd5b60003560e01c90816304ad597c1461066c57508063054f7ac01461063157806314bcec9f1461060d5780632e6f20a6146105c8578063313ce567146105ac578063461739d214610571578063558a7297146104f257806356095e11146104ad578063715018a61461044857806379ba5097146103bf5780638578005d146103385780638da5cb5b1461030f578063a035b1fe146102ec578063acfbd39e146102a7578063ce4b5bbe1461026c578063dc53858c14610227578063e30c3978146101fe578063eaa2d7b4146101b9578063f2fde38b146101455763f50a4718146100fb57600080fd5b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b346101405760203660031901126101405761015e610687565b610166610708565b60018060a01b0316806bffffffffffffffffffffffff60a01b600154161760015560018060a01b03600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610140576000366003190112610140576001546040516001600160a01b039091168152602090f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101405760003660031901126101405760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461014057600036600319011261014057602061030761069d565b604051908152f35b34610140576000366003190112610140576000546040516001600160a01b039091168152602090f35b346101405760203660031901126101405760043533600052600460205260ff60406000205416156103ae576040817f6a246b026a5fd48b881abb3342cc8ad598c6a9760423a445b2b73cf8d35378799260025563ffffffff42168063ffffffff19600354161760035582519182526020820152a1005b631decfebb60e31b60005260046000fd5b3461014057600036600319011261014057600154336001600160a01b039091160361043357600180546001600160a01b03199081169091556000805433928116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b63118cdaa760e01b6000523360045260246000fd5b3461014057600036600319011261014057610461610708565b600180546001600160a01b0319908116909155600080549182168155906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101405760403660031901126101405761050b610687565b602435908115158092036101405760207f1618a22a3b00b9ac70fd5a82f1f5cdd8cb272bd0f1b740ddf7c26ab05881dd5b91610545610708565b60018060a01b0316928360005260048252604060002060ff1981541660ff8316179055604051908152a2005b346101405760003660031901126101405760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b3461014057600036600319011261014057602060405160088152f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461014057600036600319011261014057602063ffffffff60035416604051908152f35b346101405760003660031901126101405760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b34610140576000366003190112610140576020906002548152f35b600435906001600160a01b038216820361014057565b60025460008113156106f4577f0000000000000000000000000000000000000000000000000000000000000000908181029181830414901517156106de5790565b634e487b7160e01b600052601160045260246000fd5b506ec097ce7bc90715b34b9f100000000090565b6000546001600160a01b031633036104335756fea164736f6c634300081a000a00000000000000000000000000000000000000000000000000000000000000400000000000000000000000004fe78ef65bd8edded480efab030ba680646503c80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c9137d2f8d59f693770ed0e7384129191a7d85d4

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c90816304ad597c1461066c57508063054f7ac01461063157806314bcec9f1461060d5780632e6f20a6146105c8578063313ce567146105ac578063461739d214610571578063558a7297146104f257806356095e11146104ad578063715018a61461044857806379ba5097146103bf5780638578005d146103385780638da5cb5b1461030f578063a035b1fe146102ec578063acfbd39e146102a7578063ce4b5bbe1461026c578063dc53858c14610227578063e30c3978146101fe578063eaa2d7b4146101b9578063f2fde38b146101455763f50a4718146100fb57600080fd5b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b600080fd5b346101405760203660031901126101405761015e610687565b610166610708565b60018060a01b0316806bffffffffffffffffffffffff60a01b600154161760015560018060a01b03600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610140576000366003190112610140576001546040516001600160a01b039091168152602090f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101405760003660031901126101405760206040517f0000000000000000000000000000000000000000204fce5e3e250261100000008152f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461014057600036600319011261014057602061030761069d565b604051908152f35b34610140576000366003190112610140576000546040516001600160a01b039091168152602090f35b346101405760203660031901126101405760043533600052600460205260ff60406000205416156103ae576040817f6a246b026a5fd48b881abb3342cc8ad598c6a9760423a445b2b73cf8d35378799260025563ffffffff42168063ffffffff19600354161760035582519182526020820152a1005b631decfebb60e31b60005260046000fd5b3461014057600036600319011261014057600154336001600160a01b039091160361043357600180546001600160a01b03199081169091556000805433928116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b63118cdaa760e01b6000523360045260246000fd5b3461014057600036600319011261014057610461610708565b600180546001600160a01b0319908116909155600080549182168155906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346101405760403660031901126101405761050b610687565b602435908115158092036101405760207f1618a22a3b00b9ac70fd5a82f1f5cdd8cb272bd0f1b740ddf7c26ab05881dd5b91610545610708565b60018060a01b0316928360005260048252604060002060ff1981541660ff8316179055604051908152a2005b346101405760003660031901126101405760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b3461014057600036600319011261014057602060405160088152f35b34610140576000366003190112610140576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b3461014057600036600319011261014057602063ffffffff60035416604051908152f35b346101405760003660031901126101405760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b34610140576000366003190112610140576020906002548152f35b600435906001600160a01b038216820361014057565b60025460008113156106f4577f0000000000000000000000000000000000000000204fce5e3e25026110000000908181029181830414901517156106de5790565b634e487b7160e01b600052601160045260246000fd5b506ec097ce7bc90715b34b9f100000000090565b6000546001600160a01b031633036104335756fea164736f6c634300081a000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000000000000000000000000000000000000000000400000000000000000000000004fe78ef65bd8edded480efab030ba680646503c80000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c9137d2f8d59f693770ed0e7384129191a7d85d4

-----Decoded View---------------
Arg [0] : operators (address[]): 0xC9137D2F8D59f693770ed0e7384129191A7D85D4
Arg [1] : initialOwner (address): 0x4Fe78eF65BD8EDDED480efaB030BA680646503c8

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 0000000000000000000000004fe78ef65bd8edded480efab030ba680646503c8
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 000000000000000000000000c9137d2f8d59f693770ed0e7384129191a7d85d4


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
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.