From 21dfc32e43a751d6060c0e5daaa862f4d3efec92 Mon Sep 17 00:00:00 2001 From: Ali Behjati Date: Mon, 27 Jun 2022 17:41:55 +0200 Subject: [PATCH] Abehjati/pyth-evm-contract-fire-event (#229) * Use new solidity sdk * Emit events in contract * Fix max gas issue that caused error * Add tests for PriceUpdate event * Delete a test network file --- ethereum/.openzeppelin/unknown-1337.json | 221 -------------------- ethereum/contracts/pyth/Pyth.sol | 1 + ethereum/package-lock.json | 14 +- ethereum/package.json | 2 +- ethereum/test/pyth.js | 22 +- third_party/pyth/p2w-relay/src/relay/evm.ts | 2 +- 6 files changed, 24 insertions(+), 238 deletions(-) delete mode 100644 ethereum/.openzeppelin/unknown-1337.json diff --git a/ethereum/.openzeppelin/unknown-1337.json b/ethereum/.openzeppelin/unknown-1337.json deleted file mode 100644 index 329605e3..00000000 --- a/ethereum/.openzeppelin/unknown-1337.json +++ /dev/null @@ -1,221 +0,0 @@ -{ - "manifestVersion": "3.2", - "proxies": [ - { - "address": "0xff1a0f4744e8582DF1aE09D5611b887B6a12925C", - "txHash": "0x787bc8317c315b450af392e9ce1d1b4fd0c8e6a64a2340f4e460267f57bb0245", - "kind": "uups" - } - ], - "impls": { - "5c31ffd0774368a91446d42c3ea317dd996266a4587c3c67efd448d66ae5e5c9": { - "address": "0xB2eeb93D778c364E7E2274D6299e2aa0c2Bea090", - "txHash": "0x060e021b6459b82ea6a533d3af5a61fe2ecf840eb5f0ace9553fb57ea3d1682a", - "layout": { - "storage": [ - { - "contract": "Initializable", - "label": "_initialized", - "type": "t_bool", - "src": "../@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:39" - }, - { - "contract": "Initializable", - "label": "_initializing", - "type": "t_bool", - "src": "../@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:44" - }, - { - "contract": "ContextUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "../@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "contract": "OwnableUpgradeable", - "label": "_owner", - "type": "t_address", - "src": "../@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "contract": "OwnableUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)49_storage", - "src": "../@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:87" - }, - { - "contract": "ERC1967UpgradeUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "../@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol:211" - }, - { - "contract": "UUPSUpgradeable", - "label": "__gap", - "type": "t_array(t_uint256)50_storage", - "src": "../@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol:107" - }, - { - "contract": "PythState", - "label": "_state", - "type": "t_struct(State)3714_storage", - "src": "../project:/contracts/pyth/PythState.sol:21" - } - ], - "types": { - "t_struct(State)3714_storage": { - "label": "struct PythStorage.State", - "members": [ - { - "label": "wormhole", - "type": "t_address_payable" - }, - { - "label": "pyth2WormholeChainId", - "type": "t_uint16" - }, - { - "label": "pyth2WormholeEmitter", - "type": "t_bytes32" - }, - { - "label": "latestPriceInfo", - "type": "t_mapping(t_bytes32,t_struct(PriceInfo)3636_storage)" - } - ] - }, - "t_address_payable": { - "label": "address payable" - }, - "t_uint16": { - "label": "uint16" - }, - "t_bytes32": { - "label": "bytes32" - }, - "t_mapping(t_bytes32,t_struct(PriceInfo)3636_storage)": { - "label": "mapping(bytes32 => struct PythInternalStructs.PriceInfo)" - }, - "t_struct(PriceInfo)3636_storage": { - "label": "struct PythInternalStructs.PriceInfo", - "members": [ - { - "label": "attestationTime", - "type": "t_uint256" - }, - { - "label": "arrivalTime", - "type": "t_uint256" - }, - { - "label": "arrivalBlock", - "type": "t_uint256" - }, - { - "label": "priceFeed", - "type": "t_struct(PriceFeed)2228_storage" - } - ] - }, - "t_uint256": { - "label": "uint256" - }, - "t_struct(PriceFeed)2228_storage": { - "label": "struct PythStructs.PriceFeed", - "members": [ - { - "label": "id", - "type": "t_bytes32" - }, - { - "label": "productId", - "type": "t_bytes32" - }, - { - "label": "price", - "type": "t_int64" - }, - { - "label": "conf", - "type": "t_uint64" - }, - { - "label": "expo", - "type": "t_int32" - }, - { - "label": "status", - "type": "t_enum(PriceStatus)2233" - }, - { - "label": "maxNumPublishers", - "type": "t_uint32" - }, - { - "label": "numPublishers", - "type": "t_uint32" - }, - { - "label": "emaPrice", - "type": "t_int64" - }, - { - "label": "emaConf", - "type": "t_uint64" - }, - { - "label": "publishTime", - "type": "t_uint64" - }, - { - "label": "prevPrice", - "type": "t_int64" - }, - { - "label": "prevConf", - "type": "t_uint64" - }, - { - "label": "prevPublishTime", - "type": "t_uint64" - } - ] - }, - "t_int64": { - "label": "int64" - }, - "t_uint64": { - "label": "uint64" - }, - "t_int32": { - "label": "int32" - }, - "t_enum(PriceStatus)2233": { - "label": "enum PythStructs.PriceStatus", - "members": [ - "UNKNOWN", - "TRADING", - "HALTED", - "AUCTION" - ] - }, - "t_uint32": { - "label": "uint32" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]" - }, - "t_address": { - "label": "address" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]" - }, - "t_bool": { - "label": "bool" - } - } - } - } - } -} diff --git a/ethereum/contracts/pyth/Pyth.sol b/ethereum/contracts/pyth/Pyth.sol index bdf5596c..cb971ecf 100644 --- a/ethereum/contracts/pyth/Pyth.sol +++ b/ethereum/contracts/pyth/Pyth.sol @@ -39,6 +39,7 @@ contract Pyth is PythGetters, PythSetters, AbstractPyth { if(attestation.attestationTime > latestPrice.attestationTime) { setLatestPriceInfo(attestation.priceId, newPriceInfo(attestation)); + emit PriceUpdate(attestation.priceId, attestation.publishTime); } } diff --git a/ethereum/package-lock.json b/ethereum/package-lock.json index 21d2e22a..d599abb2 100644 --- a/ethereum/package-lock.json +++ b/ethereum/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts-upgradeable": "^4.5.2", - "@pythnetwork/pyth-sdk-solidity": "^0.1.0", + "@pythnetwork/pyth-sdk-solidity": "^0.2.0", "dotenv": "^10.0.0", "elliptic": "^6.5.2", "ganache-cli": "^6.12.1", @@ -3674,9 +3674,9 @@ "dev": true }, "node_modules/@pythnetwork/pyth-sdk-solidity": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.1.0.tgz", - "integrity": "sha512-tyW8d98pnBHPhd/NS5jwCAzrOn/v+sqxUKseVXNQxohAxmuJ2QSOAypjNgaEFNKwu7DtgKQxoive2PnNJBVnXg==" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.2.0.tgz", + "integrity": "sha512-kb3pun9wRVRtRBwKakaaMdtIVHw45xbvBH9j1Fq7yJco52AdBGNHK78c7cJv5Q2JZtE0x/6yZT1p75b98M4F9w==" }, "node_modules/@redux-saga/core": { "version": "1.1.3", @@ -39998,9 +39998,9 @@ "dev": true }, "@pythnetwork/pyth-sdk-solidity": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.1.0.tgz", - "integrity": "sha512-tyW8d98pnBHPhd/NS5jwCAzrOn/v+sqxUKseVXNQxohAxmuJ2QSOAypjNgaEFNKwu7DtgKQxoive2PnNJBVnXg==" + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.2.0.tgz", + "integrity": "sha512-kb3pun9wRVRtRBwKakaaMdtIVHw45xbvBH9j1Fq7yJco52AdBGNHK78c7cJv5Q2JZtE0x/6yZT1p75b98M4F9w==" }, "@redux-saga/core": { "version": "1.1.3", diff --git a/ethereum/package.json b/ethereum/package.json index fff22fa4..0fa86941 100644 --- a/ethereum/package.json +++ b/ethereum/package.json @@ -30,7 +30,7 @@ "dependencies": { "@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts-upgradeable": "^4.5.2", - "@pythnetwork/pyth-sdk-solidity": "^0.1.0", + "@pythnetwork/pyth-sdk-solidity": "^0.2.0", "dotenv": "^10.0.0", "elliptic": "^6.5.2", "ganache-cli": "^6.12.1", diff --git a/ethereum/test/pyth.js b/ethereum/test/pyth.js index edad2ae5..a72bdc67 100644 --- a/ethereum/test/pyth.js +++ b/ethereum/test/pyth.js @@ -5,7 +5,7 @@ const BigNumber = require("bignumber.js"); const PythStructs = artifacts.require("PythStructs"); const { deployProxy, upgradeProxy } = require("@openzeppelin/truffle-upgrades"); -const { expectRevert } = require("@openzeppelin/test-helpers"); +const { expectRevert, expectEvent } = require("@openzeppelin/test-helpers"); // Use "WormholeReceiver" if you are testing with Wormhole Receiver const Wormhole = artifacts.require("Wormhole"); @@ -241,7 +241,7 @@ contract("Pyth", function () { ); updateData.push("0x" + vm) } - await contract.updatePriceFeeds(updateData); + return await contract.updatePriceFeeds(updateData); } it("should attest price updates over wormhole", async function () { @@ -251,21 +251,24 @@ contract("Pyth", function () { }); it("should attest price updates empty", async function () { - await updatePriceFeeds(this.pythProxy, []); + const receipt = await updatePriceFeeds(this.pythProxy, []); + expectEvent.notEmitted(receipt, 'PriceUpdate'); }); it("should attest price updates with multiple batches of correct order", async function () { let ts = 1647273460 let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2]); + const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch1, rawBatch2]); + expectEvent(receipt, 'PriceUpdate'); }); it("should attest price updates with multiple batches of wrong order", async function () { let ts = 1647273460 let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); - await updatePriceFeeds(this.pythProxy, [rawBatch2, rawBatch1]); + const receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2, rawBatch1]); + expectEvent(receipt, 'PriceUpdate'); }); @@ -273,7 +276,8 @@ contract("Pyth", function () { let currentTimestamp = (await web3.eth.getBlock("latest")).timestamp; let priceVal = 521; let rawBatch = generateRawBatchAttestation(currentTimestamp - 5, currentTimestamp, priceVal); - await updatePriceFeeds(this.pythProxy, [rawBatch]); + let receipt = await updatePriceFeeds(this.pythProxy, [rawBatch]); + expectEvent(receipt, 'PriceUpdate'); let first_prod_id = "0x" + "01".repeat(32); let first_price_id = "0x" + "fe".repeat(32); @@ -295,7 +299,8 @@ contract("Pyth", function () { nextTimestamp, priceVal + 5 ); - await updatePriceFeeds(this.pythProxy, [rawBatch2]); + receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2]); + expectEvent(receipt, 'PriceUpdate'); first = await this.pythProxy.queryPriceFeed(first_price_id); assert.equal(first.price, priceVal + 5); @@ -309,7 +314,8 @@ contract("Pyth", function () { nextTimestamp, priceVal + 10 ); - await updatePriceFeeds(this.pythProxy, [rawBatch3]); + receipt = await updatePriceFeeds(this.pythProxy, [rawBatch3]); + expectEvent.notEmitted(receipt, 'PriceUpdate'); first = await this.pythProxy.queryPriceFeed(first_price_id); assert.equal(first.price, priceVal + 5); diff --git a/third_party/pyth/p2w-relay/src/relay/evm.ts b/third_party/pyth/p2w-relay/src/relay/evm.ts index 945866eb..ed0d7009 100644 --- a/third_party/pyth/p2w-relay/src/relay/evm.ts +++ b/third_party/pyth/p2w-relay/src/relay/evm.ts @@ -46,7 +46,7 @@ export class EvmRelay implements Relay { : null; let tx = this.p2wContract - .updatePriceFeeds(["0x" + signedVAAs[i]], { gasLimit: 1000000 }) + .updatePriceFeeds(["0x" + signedVAAs[i]], { gasLimit: 2000000 }) .then(async (pending) => { let receipt = await pending.wait(); logger.info(