PythAggregatorV3.sol 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. // solhint-disable-next-line no-unused-vars
  29. (bool success, ) = payable(msg.sender).call{
  30. value: address(this).balance
  31. }("");
  32. }
  33. function decimals() public view virtual returns (uint8) {
  34. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  35. return uint8(-1 * int8(price.expo));
  36. }
  37. function description() public pure returns (string memory) {
  38. return "A port of a chainlink aggregator powered by pyth network feeds";
  39. }
  40. function version() public pure returns (uint256) {
  41. return 1;
  42. }
  43. function latestAnswer() public view virtual returns (int256) {
  44. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  45. return int256(price.price);
  46. }
  47. function latestTimestamp() public view returns (uint256) {
  48. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  49. return price.publishTime;
  50. }
  51. function latestRound() public view returns (uint256) {
  52. // use timestamp as the round id
  53. return latestTimestamp();
  54. }
  55. function getAnswer(uint256) public view returns (int256) {
  56. return latestAnswer();
  57. }
  58. function getTimestamp(uint256) external view returns (uint256) {
  59. return latestTimestamp();
  60. }
  61. function getRoundData(
  62. uint80 _roundId
  63. )
  64. external
  65. view
  66. returns (
  67. uint80 roundId,
  68. int256 answer,
  69. uint256 startedAt,
  70. uint256 updatedAt,
  71. uint80 answeredInRound
  72. )
  73. {
  74. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  75. return (
  76. _roundId,
  77. int256(price.price),
  78. price.publishTime,
  79. price.publishTime,
  80. _roundId
  81. );
  82. }
  83. function latestRoundData()
  84. external
  85. view
  86. returns (
  87. uint80 roundId,
  88. int256 answer,
  89. uint256 startedAt,
  90. uint256 updatedAt,
  91. uint80 answeredInRound
  92. )
  93. {
  94. PythStructs.Price memory price = pyth.getPriceUnsafe(priceId);
  95. roundId = uint80(price.publishTime);
  96. return (
  97. roundId,
  98. int256(price.price),
  99. price.publishTime,
  100. price.publishTime,
  101. roundId
  102. );
  103. }
  104. }