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
This commit is contained in:
Ali Behjati 2022-06-27 17:41:55 +02:00 committed by GitHub
parent 4667c5fd12
commit 21dfc32e43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 238 deletions

View File

@ -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"
}
}
}
}
}
}

View File

@ -39,6 +39,7 @@ contract Pyth is PythGetters, PythSetters, AbstractPyth {
if(attestation.attestationTime > latestPrice.attestationTime) { if(attestation.attestationTime > latestPrice.attestationTime) {
setLatestPriceInfo(attestation.priceId, newPriceInfo(attestation)); setLatestPriceInfo(attestation.priceId, newPriceInfo(attestation));
emit PriceUpdate(attestation.priceId, attestation.publishTime);
} }
} }

View File

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2", "@openzeppelin/contracts-upgradeable": "^4.5.2",
"@pythnetwork/pyth-sdk-solidity": "^0.1.0", "@pythnetwork/pyth-sdk-solidity": "^0.2.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"elliptic": "^6.5.2", "elliptic": "^6.5.2",
"ganache-cli": "^6.12.1", "ganache-cli": "^6.12.1",
@ -3674,9 +3674,9 @@
"dev": true "dev": true
}, },
"node_modules/@pythnetwork/pyth-sdk-solidity": { "node_modules/@pythnetwork/pyth-sdk-solidity": {
"version": "0.1.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.1.0.tgz", "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.2.0.tgz",
"integrity": "sha512-tyW8d98pnBHPhd/NS5jwCAzrOn/v+sqxUKseVXNQxohAxmuJ2QSOAypjNgaEFNKwu7DtgKQxoive2PnNJBVnXg==" "integrity": "sha512-kb3pun9wRVRtRBwKakaaMdtIVHw45xbvBH9j1Fq7yJco52AdBGNHK78c7cJv5Q2JZtE0x/6yZT1p75b98M4F9w=="
}, },
"node_modules/@redux-saga/core": { "node_modules/@redux-saga/core": {
"version": "1.1.3", "version": "1.1.3",
@ -39998,9 +39998,9 @@
"dev": true "dev": true
}, },
"@pythnetwork/pyth-sdk-solidity": { "@pythnetwork/pyth-sdk-solidity": {
"version": "0.1.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.1.0.tgz", "resolved": "https://registry.npmjs.org/@pythnetwork/pyth-sdk-solidity/-/pyth-sdk-solidity-0.2.0.tgz",
"integrity": "sha512-tyW8d98pnBHPhd/NS5jwCAzrOn/v+sqxUKseVXNQxohAxmuJ2QSOAypjNgaEFNKwu7DtgKQxoive2PnNJBVnXg==" "integrity": "sha512-kb3pun9wRVRtRBwKakaaMdtIVHw45xbvBH9j1Fq7yJco52AdBGNHK78c7cJv5Q2JZtE0x/6yZT1p75b98M4F9w=="
}, },
"@redux-saga/core": { "@redux-saga/core": {
"version": "1.1.3", "version": "1.1.3",

View File

@ -30,7 +30,7 @@
"dependencies": { "dependencies": {
"@openzeppelin/contracts": "^4.5.0", "@openzeppelin/contracts": "^4.5.0",
"@openzeppelin/contracts-upgradeable": "^4.5.2", "@openzeppelin/contracts-upgradeable": "^4.5.2",
"@pythnetwork/pyth-sdk-solidity": "^0.1.0", "@pythnetwork/pyth-sdk-solidity": "^0.2.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"elliptic": "^6.5.2", "elliptic": "^6.5.2",
"ganache-cli": "^6.12.1", "ganache-cli": "^6.12.1",

View File

@ -5,7 +5,7 @@ const BigNumber = require("bignumber.js");
const PythStructs = artifacts.require("PythStructs"); const PythStructs = artifacts.require("PythStructs");
const { deployProxy, upgradeProxy } = require("@openzeppelin/truffle-upgrades"); 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 // Use "WormholeReceiver" if you are testing with Wormhole Receiver
const Wormhole = artifacts.require("Wormhole"); const Wormhole = artifacts.require("Wormhole");
@ -241,7 +241,7 @@ contract("Pyth", function () {
); );
updateData.push("0x" + vm) updateData.push("0x" + vm)
} }
await contract.updatePriceFeeds(updateData); return await contract.updatePriceFeeds(updateData);
} }
it("should attest price updates over wormhole", async function () { it("should attest price updates over wormhole", async function () {
@ -251,21 +251,24 @@ contract("Pyth", function () {
}); });
it("should attest price updates empty", async 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 () { it("should attest price updates with multiple batches of correct order", async function () {
let ts = 1647273460 let ts = 1647273460
let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337);
let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); 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 () { it("should attest price updates with multiple batches of wrong order", async function () {
let ts = 1647273460 let ts = 1647273460
let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337); let rawBatch1 = generateRawBatchAttestation(ts - 5, ts, 1337);
let rawBatch2 = generateRawBatchAttestation(ts + 5, ts + 10, 1338); 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 currentTimestamp = (await web3.eth.getBlock("latest")).timestamp;
let priceVal = 521; let priceVal = 521;
let rawBatch = generateRawBatchAttestation(currentTimestamp - 5, currentTimestamp, priceVal); 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_prod_id = "0x" + "01".repeat(32);
let first_price_id = "0x" + "fe".repeat(32); let first_price_id = "0x" + "fe".repeat(32);
@ -295,7 +299,8 @@ contract("Pyth", function () {
nextTimestamp, nextTimestamp,
priceVal + 5 priceVal + 5
); );
await updatePriceFeeds(this.pythProxy, [rawBatch2]); receipt = await updatePriceFeeds(this.pythProxy, [rawBatch2]);
expectEvent(receipt, 'PriceUpdate');
first = await this.pythProxy.queryPriceFeed(first_price_id); first = await this.pythProxy.queryPriceFeed(first_price_id);
assert.equal(first.price, priceVal + 5); assert.equal(first.price, priceVal + 5);
@ -309,7 +314,8 @@ contract("Pyth", function () {
nextTimestamp, nextTimestamp,
priceVal + 10 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); first = await this.pythProxy.queryPriceFeed(first_price_id);
assert.equal(first.price, priceVal + 5); assert.equal(first.price, priceVal + 5);

View File

@ -46,7 +46,7 @@ export class EvmRelay implements Relay {
: null; : null;
let tx = this.p2wContract let tx = this.p2wContract
.updatePriceFeeds(["0x" + signedVAAs[i]], { gasLimit: 1000000 }) .updatePriceFeeds(["0x" + signedVAAs[i]], { gasLimit: 2000000 })
.then(async (pending) => { .then(async (pending) => {
let receipt = await pending.wait(); let receipt = await pending.wait();
logger.info( logger.info(