From 7bc1e28605ef3da2e8688b9293642e1e5d9a8e96 Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:18:24 +0530 Subject: [PATCH 1/7] added Mezo network configuration --- hardhat.config.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hardhat.config.ts b/hardhat.config.ts index 3898647..b0c2146 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -11,6 +11,8 @@ import "./tasks/deploy-pyth"; import "./tasks/deploy-contract"; import "./tasks/deploy-double-agg"; import "./tasks/update-pyth"; +import "./tasks/get-pyth-data"; +import "./tasks/update-pyth-feeds"; export default { solidity: "0.8.20", @@ -57,6 +59,10 @@ export default { url: `https://rpc.berachain.com`, accounts: [process.env.WALLET_PRIVATE_KEY || ""], }, + mezo: { + url: `https://jsonrpc-mezo.boar.network`, + accounts: [process.env.WALLET_PRIVATE_KEY || ""], + }, }, etherscan: { apiKey: { @@ -69,6 +75,7 @@ export default { berachain: process.env.BERASCAN_KEY || "", manta: "", era: process.env.ZKSYNC_KEY || "", + mezo:"TEST", }, customChains: [ { @@ -120,6 +127,14 @@ export default { browserURL: "https://explorer.zircuit.com", }, }, + { + network: "mezo", + chainId: 31612, + urls: { + apiURL: "https://api.explorer.mezo.org/api", + browserURL: "https://explorer.mezo.org" + } + }, ], }, }; From 96f5f9e8936e014985b635056693666948ba5251 Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:18:43 +0530 Subject: [PATCH 2/7] refactor PythAggregatorV3 to use constant HEART_BEAT for price retrieval --- contracts/pyth/PythAggregatorV3.sol | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/pyth/PythAggregatorV3.sol b/contracts/pyth/PythAggregatorV3.sol index 73ae593..0b3ee4e 100644 --- a/contracts/pyth/PythAggregatorV3.sol +++ b/contracts/pyth/PythAggregatorV3.sol @@ -25,6 +25,8 @@ contract PythAggregatorV3 { bytes32 public priceId; IPyth public pyth; + uint256 public constant HEART_BEAT = 1 days; + constructor(address _pyth, bytes32 _priceId) { priceId = _priceId; pyth = IPyth(_pyth); @@ -42,7 +44,7 @@ contract PythAggregatorV3 { } function decimals() public view virtual returns (uint8) { - PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, 1 days); + PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, HEART_BEAT); return uint8(-1 * int8(price.expo)); } @@ -55,12 +57,12 @@ contract PythAggregatorV3 { } function latestAnswer() public view virtual returns (int256) { - PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, 1 days); + PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, HEART_BEAT); return int256(price.price); } function latestTimestamp() public view returns (uint256) { - PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, 1 days); + PythStructs.Price memory price = pyth.getPriceNoOlderThan(priceId, HEART_BEAT); return price.publishTime; } From 5d87a794583fa57f0336bd7047157aa038110c7c Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:19:01 +0530 Subject: [PATCH 3/7] add task to retrieve Pyth price data by price ID --- tasks/get-pyth-data.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tasks/get-pyth-data.ts diff --git a/tasks/get-pyth-data.ts b/tasks/get-pyth-data.ts new file mode 100644 index 0000000..7c30372 --- /dev/null +++ b/tasks/get-pyth-data.ts @@ -0,0 +1,26 @@ +import { task } from "hardhat/config"; +import { isAddress } from "ethers"; +import { pythContracts } from "../utils/pyth"; + +task(`get-pyth-data`) + .addParam("priceid") + .setAction(async ({ priceid }, hre) => { + const pythContract = pythContracts[hre.network.name] as `0x${string}`; + + if (!isAddress(pythContract)) { + throw new Error("Invalid Pyth contract address"); + } + + console.log(`\nšŸ”— Network: ${hre.network.name}`); + console.log(`šŸ“ Pyth Contract: ${pythContract}`); + + // Get contract instance + const pyth = await hre.ethers.getContractAt("IPyth", pythContract); + + const getPriceUnsafe = await pyth.getPriceUnsafe(priceid); + console.log("Price unsafe:", getPriceUnsafe); + + const getPrice = await pyth.getPriceNoOlderThan(priceid, 86400); // 1 day in seconds + console.log("Price no older than:", getPrice); + }); + From abf04b6a44b56b2ad263f29b2c3e4c18b92e4eea Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:19:23 +0530 Subject: [PATCH 4/7] implement task to update Pyth price feeds with specified price IDs --- tasks/update-pyth-feeds.ts | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 tasks/update-pyth-feeds.ts diff --git a/tasks/update-pyth-feeds.ts b/tasks/update-pyth-feeds.ts new file mode 100644 index 0000000..2fc4e04 --- /dev/null +++ b/tasks/update-pyth-feeds.ts @@ -0,0 +1,44 @@ +import { task } from "hardhat/config"; +import { isAddress } from "ethers"; +import { pythContracts } from "../utils/pyth"; +import { EvmPriceServiceConnection } from "@pythnetwork/pyth-evm-js"; + +task("update-pyth-feeds") + .setAction(async (_, hre) => { + const pythContract = pythContracts[hre.network.name] as `0x${string}`; + + if (!isAddress(pythContract)) { + throw new Error("Invalid Pyth contract address"); + } + + console.log(`šŸ”— Network: ${hre.network.name}`); + console.log(`šŸ“ Pyth Contract: ${pythContract}`); + + // Price IDs to update + const priceIds = [ + "0xc9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33", // wbtc/usd + "0x56a3121958b01f99fdc4e1fd01e81050602c7ace3a571918bb55c6a96657cca9", // tbtc/usd + ]; + + // Get contract instance + const pyth = await hre.ethers.getContractAt("IPyth", pythContract); + + // Get connection to the Pyth network + const connection = new EvmPriceServiceConnection( + "https://hermes.pyth.network" + ); // See Hermes endpoints section below for other endpoints + + // Get price update data in bytes format + const priceUpdateData = (await connection.getPriceFeedsUpdateData( + priceIds + )) as any; + + // Get update fee. For one price id, the value of fee is 1 + const fee = await pyth.getUpdateFee(priceUpdateData); + console.log("Update fee:", fee.toString()); + + // Update price feeds + // const tx = await pyth.updatePriceFeeds(priceUpdateData, { value: fee }); + // await tx.wait(); + // console.log("Tx hash:", tx.hash); + }); From f8540d862954eb83fad7746bfa2d2efa977ec297 Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:20:30 +0530 Subject: [PATCH 5/7] update Pyth price IDs and add new tokens for tBTC and mUSD --- tasks/update-pyth.ts | 4 ++-- utils/pyth.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tasks/update-pyth.ts b/tasks/update-pyth.ts index a5bc406..514f779 100644 --- a/tasks/update-pyth.ts +++ b/tasks/update-pyth.ts @@ -11,7 +11,7 @@ task(`update-pyth`) const contract = await hre.ethers.getContractAt( "PythAggregatorV3", - "0xd04a2e318e4557bb81344ea485b63d0d55732a37" + "0x94eae1d41036c23900DB6Af8Dd27841f4E3a5906" ); const updateData: [`0x${string}`] = [priceid]; @@ -25,7 +25,7 @@ task(`update-pyth`) )) as any; const tx = await contract.updateFeeds(priceUpdateData, { - value: 1000000000n, + value: 1, }); console.log(`tx`, tx); diff --git a/utils/pyth.ts b/utils/pyth.ts index 9cc61b5..ff22055 100644 --- a/utils/pyth.ts +++ b/utils/pyth.ts @@ -12,10 +12,12 @@ export const priceIdsUSD = { usdc: "0xeaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a", usdt: "0x2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b", zero: "0x9a11b5c6c8d6d266444459316c3aee7684aaa5a5434b189a173d8cddbb3deaae", - wbtc: "0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43", + wbtc: "0xc9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33", wsteth: "0x6df640f3b8963d8f8358f791f352b8364513f6ab1cca5ed3f1f7b5448980e784", bera: "0x962088abcfdbdb6e30db2e340c8cf887d9efb311b1f2f17b155a63dbb6d40265", manta: "0xc3883bcf1101c111e9fcfe2465703c47f2b638e21fef2cce0502e6c8f416e0e2", + tbtc: "0x56a3121958b01f99fdc4e1fd01e81050602c7ace3a571918bb55c6a96657cca9", + musd: "0x0617a9b725011a126a2b9fd53563f4236501f32cf76d877644b943394606c6de", }; // MATICX: "----", @@ -31,4 +33,5 @@ export const pythContracts: { [key: string]: string } = { linea: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729", berachain: "0x2880ab155794e7179c9ee2e38200202908c17b43", blast: "0xA2aa501b19aff244D90cc15a4Cf739D2725B5729", + mezo: "0x2880aB155794e7179c9eE2e38200202908C17B43", }; From b004e0f940fe9c8d3aab7a36eb9039d7e758affb Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:25:37 +0530 Subject: [PATCH 6/7] refactor deploy-pyth task to use new deployment method --- tasks/deploy-pyth.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tasks/deploy-pyth.ts b/tasks/deploy-pyth.ts index 6ffd71a..d7b7b78 100644 --- a/tasks/deploy-pyth.ts +++ b/tasks/deploy-pyth.ts @@ -13,19 +13,23 @@ task(`deploy-pyth`) const [deployer] = await hre.ethers.getSigners(); console.log("i am", deployer.address); console.log("args", args); - const contract = await hre.ethers.deployContract("PythAggregatorV3", args); + + const contract = await hre.deployments.deploy("PythAggregatorV3", { + from: deployer.address, + args: args, + log: true, + }); - await contract.waitForDeployment(); - console.log(`deployed to`, contract.target); + console.log(`deployed to`, contract.address); // verify contract for tesnet & mainnet if (process.env.NODE_ENV != "test") { // Verify contract programmatically await hre.run("verify:verify", { - address: contract.target, + address: contract.address, constructorArguments: args, }); } else { console.log(`Contract not verified, deployed locally.`); } - }); + }); \ No newline at end of file From 998e3f74ce0acf2893f7fa91f6102e5ea7ee04d3 Mon Sep 17 00:00:00 2001 From: nikhilbajaj31 Date: Thu, 29 May 2025 11:34:13 +0530 Subject: [PATCH 7/7] refactor PythAggregatorV3 to streamline price update process and add fee retrieval function --- contracts/pyth/PythAggregatorV3.sol | 13 +++++-------- tasks/update-pyth.ts | 5 ++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/contracts/pyth/PythAggregatorV3.sol b/contracts/pyth/PythAggregatorV3.sol index 0b3ee4e..45699e4 100644 --- a/contracts/pyth/PythAggregatorV3.sol +++ b/contracts/pyth/PythAggregatorV3.sol @@ -33,14 +33,7 @@ contract PythAggregatorV3 { } function updateFeeds(bytes[] calldata priceUpdateData) public payable { - // Update the prices to the latest available values and pay the required fee for it. The `priceUpdateData` data - // should be retrieved from our off-chain Price Service API using the `pyth-evm-js` package. - // See section "How Pyth Works on EVM Chains" below for more information. - uint256 fee = pyth.getUpdateFee(priceUpdateData); - pyth.updatePriceFeeds{value: fee}(priceUpdateData); - - // refund remaining eth - payable(msg.sender).call{value: address(this).balance}(""); + pyth.updatePriceFeeds{value: msg.value}(priceUpdateData); } function decimals() public view virtual returns (uint8) { @@ -97,4 +90,8 @@ contract PythAggregatorV3 { roundId = uint80(price.publishTime); return (roundId, int256(price.price), price.publishTime, price.publishTime, roundId); } + + function getUpdateFee(bytes[] calldata priceUpdateData) public view returns (uint256) { + return pyth.getUpdateFee(priceUpdateData); + } } diff --git a/tasks/update-pyth.ts b/tasks/update-pyth.ts index 514f779..2c479af 100644 --- a/tasks/update-pyth.ts +++ b/tasks/update-pyth.ts @@ -24,8 +24,11 @@ task(`update-pyth`) updateData )) as any; + const fee = await contract.getUpdateFee(priceUpdateData); + console.log("fee", fee); + const tx = await contract.updateFeeds(priceUpdateData, { - value: 1, + value: fee, }); console.log(`tx`, tx);