Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pyth oracle implementation: Issue updating the price feeds using the Pyth oracle on ShimmerEVM Testnet/Mainnet #2934

Open
0101sg opened this issue Oct 11, 2023 · 9 comments
Assignees
Labels
bug Something isn't working

Comments

@0101sg
Copy link

0101sg commented Oct 11, 2023

Describe the bug
Pyth oracle implementation: Issue updating the price feeds using the Pyth oracle on ShimmerEVM Testnet/Mainnet

To Reproduce

Issue updating the price feeds using the Pyth oracle on ShimmerEVM Testnet/Mainnet

My team and I are facing an issue while trying to update Pyth price feeds from a contract deployed on ShimmerEVM.

Contract GetBTCPricePyth.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;


import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";

contract GetBTCPricePyth {
  IPyth pyth;


  event GotThePrice(int64 price, uint64 conf, int32 expo, uint publishTime);

  constructor() {
    pyth = IPyth(0x5f3c61944CEb01B3eAef861251Fb1E0f14b848fb); // Shimmer Testnet oracle
  }


  function getBtcUsdPrice(
    bytes[] calldata priceUpdateData
  ) public payable  {
    pyth.updatePriceFeeds{ value: msg.value }(priceUpdateData);

    PythStructs.Price memory price =  pyth.getPrice(0xf9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b); // BTC/USD Testnet

    emit GotThePrice(price.price, price.conf, price.expo, price.publishTime);
  }
}

Hardhat deployment script

import { ethers } from 'hardhat'
import PythAbi from '@pythnetwork/pyth-sdk-solidity/abis/IPyth.json' assert { type: 'json' }
import { EvmPriceServiceConnection } from '@pythnetwork/pyth-evm-js'

async function main() {
  const connection = new EvmPriceServiceConnection(
    'https://xc-testnet.pyth.network', // Pyth Testnet
  )

  const priceIds = [
    '0xf9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b', // BTC/USD Testnet
  ]
  const priceUpdateData = await connection.getPriceFeedsUpdateData(priceIds)

  const contractAddress = '0x5f3c61944CEb01B3eAef861251Fb1E0f14b848fb' // Shimmer Testnet

  const provider = ethers.getDefaultProvider(
    'https://shimmerevm-testnet.rpc.thirdweb.com', // Shimmer Testnet
  )

  const contract = new ethers.Contract(contractAddress, PythAbi, provider)

  const [deployer] = await ethers.getSigners()

  const updateFee = await contract
    .connect(deployer)
    .getUpdateFee(priceUpdateData)

  console.log(`Update fee is ${updateFee.toString()}`)

  const updatePriceTxn = await contract
    .connect(deployer)
    .updatePriceFeeds(priceUpdateData, {
      value: updateFee,
    })

  console.log(`Price Updated ${updatePriceTxn.hash}`)

  const GetBTCPricePyth = await ethers.getContractFactory('GetBTCPricePyth')
  console.log('Deploying GetBTCPricePyth...')
  const getPriceContract = await GetBTCPricePyth.deploy()
  await getPriceContract.deployed()
  console.log(`Deployed the getter to ${getPriceContract.address}`)

  console.log('Calling the getter...')
  const tx = await getPriceContract.getBtcUsdPrice(priceUpdateData, {
    value: updateFee,
  })
  await tx.wait(1)

  console.log(`Price Updated ${tx.hash}`)
}

main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})

When running the script with the ShimmerEVM Testnet specified, an error occurs.

~/Desktop/HardHat-Env > npx hardhat run --network shimmerEVMTestNet ./scripts/getBTCPricePyth.ts                           
Update fee is 1
Price Updated 0xba6acfa46bdf09bd00146fbe6a71718315feb87c3397e79f818f46808cfcacf5
Deploying GetBTCPricePyth...
Deployed the getter to 0xFaE74082329DeC17C5ab85CcF4bfc3611d92B138
Calling the getter...
ProviderError: request might require more gas than it is allowed by the VM (50000000), or will never succeed
    at HttpProvider.request (/home/mantasm/Desktop/HardHat-Env/node_modules/hardhat/src/internal/core/providers/http.ts:88:21)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async EthersProviderWrapper.send (/home/mantasm/Desktop/HardHat-Env/node_modules/@nomiclabs/hardhat-ethers/src/internal/ethers-provider-wrapper.ts:13:20)
 

As we can see, the price update worked when calling from the Hardhat script, but it does not allow us to execute the function which has the price update functionality in the contract itself.

If we increase the gasLimit in the deployment script like so:

  console.log('Calling the getter...')
 const tx = await getPriceContract.getBtcUsdPrice(priceUpdateData, {
   value: updateFee,
   gasLimit: 500000000,
 })
 await tx.wait(1)

And then try to run the script again, we get an output like this:

~/Desktop/HardHat-Env > npx hardhat run --network shimmerEVMTestNet ./scripts/getBTCPricePyth.ts                           
Update fee is 1
Price Updated 0x6753e2f1f4b22e77269d2c8bddbbbb9f2ddcb1e9c76983804dc9338874fe5644
Deploying GetBTCPricePyth...
Deployed the getter to 0x3fbFcd062c4EB60e53Eaa4c675A457e615aecDA4
Calling the getter...
Error: transaction failed [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (transactionHash="0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc", transaction={"hash":"0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc","type":0,"accessList":null,"blockHash":"0x311701a416f1e4495dc88bac0ac3263f054e48801d600cc76d38d30068cfb4de","blockNumber":1058358,"transactionIndex":0,"confirmations":2,"from":"0x03f16B5363CdC3A002e3b8c770273AD0EB034CaB","gasPrice":{"type":"BigNumber","hex":"0xe8d4a51000"},"gasLimit":{"type":"BigNumber","hex":"0x1dcd6500"},"to":"0x3fbFcd062c4EB60e53Eaa4c675A457e615aecDA4","value":{"type":"BigNumber","hex":"0x01"},"nonce":140,"data":"0x998f6211000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000039b0100000000010074fd929c4a76b40ce737558bf93cf320be80286c5123cdb573fb452ba7327c5a20241587d2a2ef1768e21402616f543dcd0521822b5a6dddce5d1ec8cc662ac0006526d89e00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6000000001395991d0150325748000300010001020005009d1cdb1a5e1e3456d2977ee0d3d70765239f08a42855b9508fd479e15c6dc4d1feecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a00000004c69f8fd800000000004e81a8fffffff800000004c84d38d0000000000085b8c7010000000200000002000000006526d89e000000006526d89c000000006526d89b00000004c69f8fd800000000004e81a8000000006526d89c6a20671c0e3f8cb219ce3f46e5ae096a4f2fdf936d2bd4da8925f70087d51dd830029479598797290e3638a1712c29bde2367d0eca794f778b25b5a472f192de00000004f532aa4c0000000000917453fffffff800000004f5bf8f0c00000000006f1dbc010000000200000002000000006526d89e000000006526d89c000000006526d89b00000004f52ed9bc00000000009544e3000000006526d89c28fe05d2708c6571182a7c9d1ff457a221b465edf5ea9af1373f9562d16b8d15f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b0000026bf87dcbef000000002444f921fffffff80000026ec4bc1a8000000000270e449a010000000200000002000000006526d89e000000006526d89c000000006526d89b0000026bf8500530000000002472bfe0000000006526d89c8b38db700e8b34640e681ec9a73e89608bda29415547a224f96585192b4b9dc794bce4aee88fdfa5b58d81090bd6b3784717fa6df85419d9f04433bb3d615d5c00000000028f368d000000000000abd4fffffff80000000002907099000000000000c30a010000000100000002000000006526d89e000000006526d89e000000006526d89c00000000028f31db000000000000c44d000000006526d89c3b69a3cf075646c5fd8148b705b8107e61a1a253d5d8a84355dcb628b3f1d12031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae000000000058675900000000000009dafffffff80000000000588f620000000000000812010000000200000002000000006526d89e000000006526d89b000000006526d89b00000000005867bd0000000000000a3e000000006526d89b0000000000","r":"0x0f7cebe0c537120334d40c7dd88f519351b62844778a68e973aca01fb15ce599","s":"0x154ebf289448b8484e7a472d56769f90d76776e9a2dcee7feba36315df93f42e","v":2180,"creates":null,"chainId":1072}, receipt={"to":"0x3fbFcd062c4EB60e53Eaa4c675A457e615aecDA4","from":"0x03f16B5363CdC3A002e3b8c770273AD0EB034CaB","contractAddress":"0x0000000000000000000000000000000000000000","transactionIndex":0,"gasUsed":{"type":"BigNumber","hex":"0xa46e"},"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","blockHash":"0x311701a416f1e4495dc88bac0ac3263f054e48801d600cc76d38d30068cfb4de","transactionHash":"0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc","logs":[],"blockNumber":1058358,"confirmations":2,"cumulativeGasUsed":{"type":"BigNumber","hex":"0xa46e"},"status":0,"type":0,"byzantium":true}, code=CALL_EXCEPTION, version=providers/5.7.2)
   at Logger.makeError (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/logger/src.ts/index.ts:269:28)
   at Logger.throwError (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/logger/src.ts/index.ts:281:20)
   at EthersProviderWrapper.<anonymous> (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/providers/src.ts/base-provider.ts:1549:24)
   at step (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/providers/lib/base-provider.js:48:23)
   at Object.next (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/providers/lib/base-provider.js:29:53)
   at fulfilled (/home/mantasm/Desktop/HardHat-Env/node_modules/@ethersproject/providers/lib/base-provider.js:20:58)
   at processTicksAndRejections (node:internal/process/task_queues:95:5) {
 reason: 'transaction failed',
 code: 'CALL_EXCEPTION',
 transactionHash: '0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc',
 transaction: {
   hash: '0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc',
   type: 0,
   accessList: null,
   blockHash: '0x311701a416f1e4495dc88bac0ac3263f054e48801d600cc76d38d30068cfb4de',
   blockNumber: 1058358,
   transactionIndex: 0,
   confirmations: 2,
   from: '0x03f16B5363CdC3A002e3b8c770273AD0EB034CaB',
   gasPrice: BigNumber { value: "1000000000000" },
   gasLimit: BigNumber { value: "500000000" },
   to: '0x3fbFcd062c4EB60e53Eaa4c675A457e615aecDA4',
   value: BigNumber { value: "1" },
   nonce: 140,
   data: '0x998f6211000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000039b0100000000010074fd929c4a76b40ce737558bf93cf320be80286c5123cdb573fb452ba7327c5a20241587d2a2ef1768e21402616f543dcd0521822b5a6dddce5d1ec8cc662ac0006526d89e00000000001aa27839d641b07743c0cb5f68c51f8cd31d2c0762bec00dc6fcd25433ef1ab5b6000000001395991d0150325748000300010001020005009d1cdb1a5e1e3456d2977ee0d3d70765239f08a42855b9508fd479e15c6dc4d1feecf553770d9b10965f8fb64771e93f5690a182edc32be4a3236e0caaa6e0581a00000004c69f8fd800000000004e81a8fffffff800000004c84d38d0000000000085b8c7010000000200000002000000006526d89e000000006526d89c000000006526d89b00000004c69f8fd800000000004e81a8000000006526d89c6a20671c0e3f8cb219ce3f46e5ae096a4f2fdf936d2bd4da8925f70087d51dd830029479598797290e3638a1712c29bde2367d0eca794f778b25b5a472f192de00000004f532aa4c0000000000917453fffffff800000004f5bf8f0c00000000006f1dbc010000000200000002000000006526d89e000000006526d89c000000006526d89b00000004f52ed9bc00000000009544e3000000006526d89c28fe05d2708c6571182a7c9d1ff457a221b465edf5ea9af1373f9562d16b8d15f9c0172ba10dfa4d19088d94f5bf61d3b54d5bd7483a322a982e1373ee8ea31b0000026bf87dcbef000000002444f921fffffff80000026ec4bc1a8000000000270e449a010000000200000002000000006526d89e000000006526d89c000000006526d89b0000026bf8500530000000002472bfe0000000006526d89c8b38db700e8b34640e681ec9a73e89608bda29415547a224f96585192b4b9dc794bce4aee88fdfa5b58d81090bd6b3784717fa6df85419d9f04433bb3d615d5c00000000028f368d000000000000abd4fffffff80000000002907099000000000000c30a010000000100000002000000006526d89e000000006526d89e000000006526d89c00000000028f31db000000000000c44d000000006526d89c3b69a3cf075646c5fd8148b705b8107e61a1a253d5d8a84355dcb628b3f1d12031775e1d6897129e8a84eeba975778fb50015b88039e9bc140bbd839694ac0ae000000000058675900000000000009dafffffff80000000000588f620000000000000812010000000200000002000000006526d89e000000006526d89b000000006526d89b00000000005867bd0000000000000a3e000000006526d89b0000000000',
   r: '0x0f7cebe0c537120334d40c7dd88f519351b62844778a68e973aca01fb15ce599',
   s: '0x154ebf289448b8484e7a472d56769f90d76776e9a2dcee7feba36315df93f42e',
   v: 2180,
   creates: null,
   chainId: 1072,
   wait: [Function (anonymous)]
 },
 receipt: {
   to: '0x3fbFcd062c4EB60e53Eaa4c675A457e615aecDA4',
   from: '0x03f16B5363CdC3A002e3b8c770273AD0EB034CaB',
   contractAddress: '0x0000000000000000000000000000000000000000',
   transactionIndex: 0,
   gasUsed: BigNumber { value: "42094" },
   logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
   blockHash: '0x311701a416f1e4495dc88bac0ac3263f054e48801d600cc76d38d30068cfb4de',
   transactionHash: '0x02710dc57a45d8c641c1167074287cb3893836f435c55f42979692aecb77aabc',
   logs: [],
   blockNumber: 1058358,
   confirmations: 2,
   cumulativeGasUsed: BigNumber { value: "42094" },
   status: 0,
   type: 0,
   byzantium: true
 }
}

With the gasLimit set to 500000000, we are able to call the function, but the transaction reverts.

When using the same contract and script, but changing the parameters to Sepolia like so:

Contract GetBTCPricePyth.sol

  constructor() {
    pyth = IPyth(0x2880aB155794e7179c9eE2e38200202908C17B43); // Sepolia oracle
  }

Hardhat deployment script

  const contractAddress = '0x2880aB155794e7179c9eE2e38200202908C17B43' // Sepolia

  const provider = ethers.getDefaultProvider(
    'https://sepolia.rpc.thirdweb.com', // Sepolia
  )

We then get the following output:

~/Desktop/HardHat-Env > npx hardhat run --network sepolia ./scripts/getBTCPricePyth.ts                                
Update fee is 1
Price Updated 0x9cf992359ead2d0cd5230e652fccc049fc55140ec4be47c5c4a7cf9d10b51105
Deploying GetBTCPricePyth...
Deployed the getter to 0xaBcF204b5cBaa9EeB6ACFeA9888F16a83f0EdecA
Calling the getter...
Price Updated 0xfcf8aed40e38365821db738476588144b66b6795fae4cdd8110df8ac8e69c52f

Using the Sepolia network and all the transactions go through and work as expected.

Dependencies used

    "@pythnetwork/pyth-evm-js": "^1.29.0",
    "@pythnetwork/pyth-sdk-solidity": "^2.2.1"

Solidity Version 0.8.18

Network and versioning

  • Shimmer Testnet
  • JSON/RPC Websocke ~ Smart Contracts
@0101sg 0101sg added the bug Something isn't working label Oct 11, 2023
@jorgemmsilva
Copy link
Contributor

the contract you're calling is reverting the transaction.

https://docs.ethers.org/v5/troubleshooting/errors/#help-CALL_EXCEPTION

@Mantas-M
Copy link

the contract you're calling is reverting the transaction.

https://docs.ethers.org/v5/troubleshooting/errors/#help-CALL_EXCEPTION

Is there a specific reason you could identify why this happens? As the transaction seems to not get reverted on the Sepolia network, but in the code we can see that nothing besides the contract and RPC changes.

@jorgemmsilva
Copy link
Contributor

that's what this message means:

ProviderError: request might require more gas than it is allowed by the VM (50000000), or will never succeed

and you can see it when you execute:

~/Desktop/HardHat-Env > npx hardhat run --network shimmerEVMTestNet ./scripts/getBTCPricePyth.ts                           
...
 reason: 'transaction failed',
 code: 'CALL_EXCEPTION',
...

I don't know what you're trying to do exactly, but it seems a little weird that a function called getBtcUsdPrice calls an update function (updatePriceFeeds). Usually getters only get some value, they shouldn't update anything.

function getBtcUsdPrice(
    bytes[] calldata priceUpdateData
  ) public payable  {
    pyth.updatePriceFeeds{ value: msg.value }(priceUpdateData);

@Mantas-M
Copy link

My apologies, you may not be familiar with the way Pyth works.

As you can see from their documentation example here.

The reason of updating the price right before getting it is to be sure that the price is the latest one, so then it could be used further in the smart contract logic.

@Mantas-M
Copy link

that's what this message means:

ProviderError: request might require more gas than it is allowed by the VM (50000000), or will never succeed

and you can see it when you execute:

~/Desktop/HardHat-Env > npx hardhat run --network shimmerEVMTestNet ./scripts/getBTCPricePyth.ts                           
...
 reason: 'transaction failed',
 code: 'CALL_EXCEPTION',
...

I don't know what you're trying to do exactly, but it seems a little weird that a function called getBtcUsdPrice calls an update function (updatePriceFeeds). Usually getters only get some value, they shouldn't update anything.

function getBtcUsdPrice(
    bytes[] calldata priceUpdateData
  ) public payable  {
    pyth.updatePriceFeeds{ value: msg.value }(priceUpdateData);

I understand that the issue happens in the way you outlined here and the way that was described in the initial issue description.

However the focus of the issue, from my understanding, is not why does a function that gets a price also updates it, but rather why can it not update on the ShimmerEVM network while it works on Sepolia.

@jorgemmsilva
Copy link
Contributor

Why it works on Sepolia and not on ShimmerEVM might be due to a multitude of reasons. you must figure out why the contract is reverting the transaction in order to answer that question.

To me it seems that the Pyth contract is rejecting that call for whatever reason. Could be that the price data you're sending has an old timestamp, or the price is too far away from whatever values the oracle has.

@Mantas-M
Copy link

Mantas-M commented Oct 12, 2023

The odd thing is, that the same price data is passed in to the updatePriceFeeds function outside of the contract, it works fine.
And the issue is with updating the price so I do not believe it would revert for trying to update an old price.

So the issue seems to be specific to calling the function on a contract deployed to the Shimmer network.

@fijter
Copy link
Contributor

fijter commented Oct 12, 2023

Can you please verify the deployed testnet contract for easier debug?

@Mantas-M
Copy link

Sure, the contract from the example can be found here.

@iotaledger iotaledger deleted a comment Oct 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants