PythAggregatorV3.sol 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // SPDX-License-Identifier: Apache 2
  2. pragma solidity ^0.8.0;
  3. import {PythStructs} from "./PythStructs.sol";
  4. import {IPyth} from "./IPyth.sol";
  5. // This interface is forked from the Zerolend Adapter found here:
  6. // https://github.com/zerolend/pyth-oracles/blob/master/contracts/PythAggregatorV3.sol
  7. // Original license found under licenses/zerolend-pyth-oracles.md
  8. /**
  9. * @title A port of the ChainlinkAggregatorV3 interface that supports Pyth price feeds
  10. * @notice This does not store any roundId information on-chain. Please review the code before using this implementation.
  11. * Users should deploy an instance of this contract to wrap every price feed id that they need to use.
  12. */
  13. contract PythAggregatorV3 {
  14. bytes32 public priceId;
  15. IPyth public pyth;
  16. constructor(address _pyth, bytes32 _priceId) {
  17. priceId = _priceId;
  18. pyth = IPyth(_pyth);
  19. }
  20. // Wrapper function to update the underlying Pyth price feeds. Not part of the AggregatorV3 interface but useful.
  21. function updateFeeds(bytes[] calldata priceUpdateData) public payable {
  22. // Update the prices to the latest available values and pay the required fee for it. The `priceUpdateData` data
  23. // should be retrieved from our off-chain Price Service API using the `hermes-client` package.
  24. // See section "How Pyth Works on EVM Chains" below for more information.
  25. uint fee = pyth.getUpdateFee(priceUpdateData);
  26. pyth.updatePriceFeeds{value: fee}(priceUpdateData);
  27. // refund remaining eth
  28. payable(msg.sender).call{value: address(this).balance}("");
  29. }
  30. function decimals() public view virtual returns (uint8) {
  31. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  32. return uint8(-1 * int8(price.expo));
  33. }
  34. function description() public pure returns (string memory) {
  35. return "A port of a chainlink aggregator powered by pyth network feeds";
  36. }
  37. function version() public pure returns (uint256) {
  38. return 1;
  39. }
  40. function latestAnswer() public view virtual returns (int256) {
  41. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  42. return int256(price.price);
  43. }
  44. function latestTimestamp() public view returns (uint256) {
  45. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  46. return price.publishTime;
  47. }
  48. function latestRound() public view returns (uint256) {
  49. // use timestamp as the round id
  50. return latestTimestamp();
  51. }
  52. function getAnswer(uint256) public view returns (int256) {
  53. return latestAnswer();
  54. }
  55. function getTimestamp(uint256) external view returns (uint256) {
  56. return latestTimestamp();
  57. }
  58. function getRoundData(
  59. uint80 _roundId
  60. )
  61. external
  62. view
  63. returns (
  64. uint80 roundId,
  65. int256 answer,
  66. uint256 startedAt,
  67. uint256 updatedAt,
  68. uint80 answeredInRound
  69. )
  70. {
  71. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  72. return (
  73. _roundId,
  74. int256(price.price),
  75. price.publishTime,
  76. price.publishTime,
  77. _roundId
  78. );
  79. }
  80. function latestRoundData()
  81. external
  82. view
  83. returns (
  84. uint80 roundId,
  85. int256 answer,
  86. uint256 startedAt,
  87. uint256 updatedAt,
  88. uint80 answeredInRound
  89. )
  90. {
  91. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  92. roundId = uint80(price.publishTime);
  93. return (
  94. roundId,
  95. int256(price.price),
  96. price.publishTime,
  97. price.publishTime,
  98. roundId
  99. );
  100. }
  101. }