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:
parent
4667c5fd12
commit
21dfc32e43
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Reference in New Issue