99 lines
3.2 KiB
Solidity
99 lines
3.2 KiB
Solidity
// 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");
|
|
}
|
|
}
|