// contracts/Bridge.sol // SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.0; import "../libraries/external/BytesLib.sol"; import "./PythGetters.sol"; import "./PythSetters.sol"; import "./PythStructs.sol"; import "./PythGovernance.sol"; contract Pyth is PythGovernance { using BytesLib for bytes; function attestPrice(bytes memory encodedVm) public returns (PythStructs.PriceAttestation memory pa) { (IWormhole.VM memory vm, bool valid, string memory reason) = wormhole().parseAndVerifyVM(encodedVm); require(valid, reason); require(verifyPythVM(vm), "invalid emitter"); PythStructs.PriceAttestation memory price = parsePriceAttestation(vm.payload); PythStructs.PriceAttestation memory latestPrice = latestAttestation(price.productId, price.priceType); if(price.timestamp > latestPrice.timestamp) { setLatestAttestation(price.productId, price.priceType, price); } return price; } function verifyPythVM(IWormhole.VM memory vm) public view returns (bool valid) { if (vm.emitterChainId != pyth2WormholeChainId()) { return false; } if (vm.emitterAddress != pyth2WormholeContract()) { return false; } return true; } function parsePriceAttestation(bytes memory encodedPriceAttestation) public pure returns (PythStructs.PriceAttestation memory pa) { uint index = 0; pa.magic = encodedPriceAttestation.toUint32(index); index += 4; require(pa.magic == 0x50325748, "invalid protocol"); pa.version = encodedPriceAttestation.toUint16(index); index += 2; require(pa.version == 1, "invalid protocol"); pa.payloadId = encodedPriceAttestation.toUint8(index); index += 1; require(pa.payloadId == 1, "invalid PriceAttestation"); pa.productId = encodedPriceAttestation.toBytes32(index); index += 32; pa.priceId = encodedPriceAttestation.toBytes32(index); index += 32; pa.priceType = encodedPriceAttestation.toUint8(index); index += 1; pa.price = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.exponent = int32(encodedPriceAttestation.toUint32(index)); index += 4; pa.twap.value = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.twap.numerator = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.twap.denominator = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.twac.value = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.twac.numerator = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.twac.denominator = int64(encodedPriceAttestation.toUint64(index)); index += 8; pa.confidenceInterval = encodedPriceAttestation.toUint64(index); index += 8; pa.status = encodedPriceAttestation.toUint8(index); index += 1; pa.corpAct = encodedPriceAttestation.toUint8(index); index += 1; pa.timestamp = encodedPriceAttestation.toUint64(index); index += 8; require(encodedPriceAttestation.length == index, "invalid PriceAttestation"); } }