PendlePTPriceAggregator

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "@openzeppelin/contracts/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @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, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}
"
    },
    "@openzeppelin/contracts/math/SignedSafeMath.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity ^0.7.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations with safety checks that revert on error.
 */
library SignedSafeMath {
    int256 constant private _INT256_MIN = -2**255;

    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        // 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 0;
        }

        require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

        int256 c = a * b;
        require(c / a == b, "SignedSafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        require(b != 0, "SignedSafeMath: division by zero");
        require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

        int256 c = a / b;

        return c;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a - b;
        require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

        return c;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        int256 c = a + b;
        require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

        return c;
    }
}
"
    },
    "contracts/interfaces/IAggregatorV3Interface.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6;

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

  function latestRoundData()
    external
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
"
    },
    "contracts/interfaces/IAssetHandler.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity >=0.7.6;
pragma abicoder v2;

interface IAssetHandler {
  event AddedAsset(address asset, uint16 assetType, address aggregator);
  event RemovedAsset(address asset);

  struct Asset {
    address asset;
    uint16 assetType;
    address aggregator;
  }

  function addAsset(address asset, uint16 assetType, address aggregator) external;

  function addAssets(Asset[] memory assets) external;

  function removeAsset(address asset) external;

  function priceAggregators(address asset) external view returns (address);

  function assetTypes(address asset) external view returns (uint16);

  function getUSDPrice(address asset) external view returns (uint256);
}
"
    },
    "contracts/interfaces/IPoolFactory.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity >=0.7.6;

interface IPoolFactory {
  function governanceAddress() external view returns (address);

  function isPool(address pool) external view returns (bool);

  function customCooldownWhitelist(address from) external view returns (bool);

  function receiverWhitelist(address to) external view returns (bool);

  function emitPoolEvent() external;

  function emitPoolManagerEvent() external;

  function isValidAsset(address asset) external view returns (bool);

  function getAssetPrice(address asset) external view returns (uint256);

  function getAssetHandler() external view returns (address);
}
"
    },
    "contracts/priceAggregators/PendlePTPriceAggregator.sol": {
      "content": "//
//        __  __    __  ________  _______    ______   ________
//       /  |/  |  /  |/        |/       \  /      \ /        |
//   ____$$ |$$ |  $$ |$$$$$$$$/ $$$$$$$  |/$$$$$$  |$$$$$$$$/
//  /    $$ |$$ |__$$ |$$ |__    $$ |  $$ |$$ | _$$/ $$ |__
// /$$$$$$$ |$$    $$ |$$    |   $$ |  $$ |$$ |/    |$$    |
// $$ |  $$ |$$$$$$$$ |$$$$$/    $$ |  $$ |$$ |$$$$ |$$$$$/
// $$ \__$$ |$$ |  $$ |$$ |_____ $$ |__$$ |$$ \__$$ |$$ |_____
// $$    $$ |$$ |  $$ |$$       |$$    $$/ $$    $$/ $$       |
//  $$$$$$$/ $$/   $$/ $$$$$$$$/ $$$$$$$/   $$$$$$/  $$$$$$$$/
//
// dHEDGE DAO - https://dhedge.org
//
// Copyright (c) 2025 dHEDGE DAO
//
// SPDX-License-Identifier: MIT

pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

import {Math} from "@openzeppelin/contracts/math/Math.sol";
import {SignedSafeMath} from "@openzeppelin/contracts/math/SignedSafeMath.sol";

import {IPoolFactory} from "../interfaces/IPoolFactory.sol";
import {IAggregatorV3Interface} from "../interfaces/IAggregatorV3Interface.sol";
import {UnderlyingAssetOracleUpdater} from "./UnderlyingAssetOracleUpdater.sol";

contract PendlePTPriceAggregator is IAggregatorV3Interface, UnderlyingAssetOracleUpdater {
  using Math for uint256;
  using SignedSafeMath for int256;

  IAggregatorV3Interface public immutable pendleChainlinkOracle;
  uint8 public immutable pendleChainlinkOracleDecimals;

  constructor(
    address _syEquivalentToken,
    IAggregatorV3Interface _pendleChainlinkOracle,
    IPoolFactory _poolFactory
  ) UnderlyingAssetOracleUpdater(_syEquivalentToken, _poolFactory) {
    require(address(_pendleChainlinkOracle) != address(0), "invalid address");

    pendleChainlinkOracle = _pendleChainlinkOracle;
    pendleChainlinkOracleDecimals = _pendleChainlinkOracle.decimals();
  }

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

  function latestRoundData()
    external
    view
    override
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
  {
    (, int256 ptPrice, , uint256 ptPriceUpdateAt, ) = pendleChainlinkOracle.latestRoundData();
    (, int256 underlyingPrice, , uint256 underlyingUpdatedAt, ) = underlyingAggregator.latestRoundData();

    // Answer is in underlyingAggregator decimals
    answer = (ptPrice.mul(underlyingPrice)).div(int256(10 ** pendleChainlinkOracleDecimals));
    // Adjust answer to 8 decimals
    answer = answer.mul(1e8).div(int256(10 ** underlyingAggregatorDecimals));

    return (0, answer, 0, underlyingUpdatedAt.min(ptPriceUpdateAt), 0);
  }
}
"
    },
    "contracts/priceAggregators/UnderlyingAssetOracleUpdater.sol": {
      "content": "// SPDX-License-Identifier: MIT

pragma solidity >=0.7.6;

import {IAggregatorV3Interface} from "../interfaces/IAggregatorV3Interface.sol";
import {IAssetHandler} from "../interfaces/IAssetHandler.sol";
import {IPoolFactory} from "../interfaces/IPoolFactory.sol";

abstract contract UnderlyingAssetOracleUpdater {
  address public underlyingAsset;
  IPoolFactory public poolFactory;

  IAggregatorV3Interface public underlyingAggregator;
  uint8 public underlyingAggregatorDecimals;

  constructor(address _underlyingAsset, IPoolFactory _poolFactory) {
    require(address(_poolFactory) != address(0) && _underlyingAsset != address(0), "invalid address");

    underlyingAsset = _underlyingAsset;
    poolFactory = _poolFactory;

    updateUnderlyingAggregator();
  }

  /// @dev In case the underlying asset aggregator is changed within our system, anyone can call this function to update the child aggregator (eliminates the need for redeploying the contract)
  function updateUnderlyingAggregator() public {
    address _underlyingAggregator = IAssetHandler(poolFactory.getAssetHandler()).priceAggregators(underlyingAsset);

    require(_underlyingAggregator != address(0), "invalid aggregator");

    uint8 _underlyingAggregatorDecimals = IAggregatorV3Interface(_underlyingAggregator).decimals();

    require(_underlyingAggregatorDecimals > 0, "invalid decimals");

    underlyingAggregator = IAggregatorV3Interface(_underlyingAggregator);
    underlyingAggregatorDecimals = _underlyingAggregatorDecimals;
  }
}
"
    }
  },
  "settings": {
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "optimizer": {
      "enabled": true,
      "runs": 20
    }
  }
}}

Tags:
Factory|addr:0xec833ebd514526383213cb0a133626ecc91f54b9|verified:true|block:23742935|tx:0xfd74f0c448c6d7ba06c57ea1be75093fe0202387c395cedbf14eacac0cfd0455|first_check:1762508747

Submitted on: 2025-11-07 10:45:48

Comments

Log in to comment.

No comments yet.