Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streams RWAs #86

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,43 @@ interface IFeeManager {
}

contract StreamsUpkeepRegistrar is ILogAutomation, StreamsLookupCompatibleInterface {
error InvalidReportVersion(uint16 version); // Thrown when an unsupported report version is provided to verifyReport.

LinkTokenInterface public immutable i_link;
AutomationRegistrarInterface public immutable i_registrar;

struct Report {
bytes32 feedId; // The feed ID the report has data for
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable
uint32 observationsTimestamp; // Latest timestamp for which price is applicable
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (WETH/ETH)
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK
uint32 expiresAt; // Latest timestamp where the report can be verified onchain
int192 price; // DON consensus median price, carried to 8 decimal places
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation
/**
* @dev Represents a data report from a Data Streams feed for v3 schema (crypto feeds).
* The `price`, `bid`, and `ask` values are carried to either 8 or 18 decimal places, depending on the feed.
* For more information, see https://docs.chain.link/data-streams/crypto-feeds and https://docs.chain.link/data-streams/reference/report-schema
*/
struct ReportV3 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median price (8 or 18 decimals).
int192 bid; // Simulated price impact of a buy order up to the X% depth of liquidity utilisation (8 or 18 decimals).
int192 ask; // Simulated price impact of a sell order up to the X% depth of liquidity utilisation (8 or 18 decimals).
}

/**
* @dev Represents a data report from a Data Streams feed for v4 schema (RWA feeds).
* The `price` value is carried to either 8 or 18 decimal places, depending on the feed.
* The `marketStatus` indicates whether the market is currently open. Possible values: `0` (`Unknown`), `1` (`Closed`), `2` (`Open`).
* For more information, see https://docs.chain.link/data-streams/rwa-feeds and https://docs.chain.link/data-streams/reference/report-schema-v4
*/
struct ReportV4 {
bytes32 feedId; // The feed ID the report has data for.
uint32 validFromTimestamp; // Earliest timestamp for which price is applicable.
uint32 observationsTimestamp; // Latest timestamp for which price is applicable.
uint192 nativeFee; // Base cost to validate a transaction using the report, denominated in the chain’s native token (e.g., WETH/ETH).
uint192 linkFee; // Base cost to validate a transaction using the report, denominated in LINK.
uint32 expiresAt; // Latest timestamp where the report can be verified onchain.
int192 price; // DON consensus median benchmark price (8 or 18 decimals).
uint32 marketStatus; // The DON's consensus on whether the market is currently open.
}

struct Quote {
Expand All @@ -102,11 +126,11 @@ contract StreamsUpkeepRegistrar is ILogAutomation, StreamsLookupCompatibleInterf
address public FEE_ADDRESS;
string public constant DATASTREAMS_FEEDLABEL = "feedIDs";
string public constant DATASTREAMS_QUERYLABEL = "timestamp";
int192 public s_last_retrieved_price;
int192 public lastDecodedPrice;
uint256 s_upkeepID;
bytes public s_LogTriggerConfig;

// Find a complete list of IDs at https://docs.chain.link/data-streams/stream-ids
// Find a complete list of IDs at https://docs.chain.link/data-streams/crypto-feeds
string[] public feedIds;

constructor(
Expand Down Expand Up @@ -185,6 +209,14 @@ contract StreamsUpkeepRegistrar is ILogAutomation, StreamsLookupCompatibleInterf
(, /* bytes32[3] reportContextData */ bytes memory reportData) =
abi.decode(unverifiedReport, (bytes32[3], bytes));

// Extract report version from reportData
uint16 reportVersion = (uint16(uint8(reportData[0])) << 8) | uint16(uint8(reportData[1]));

// Validate report version
if (reportVersion != 3 && reportVersion != 4) {
revert InvalidReportVersion(uint8(reportVersion));
}

// Report verification fees
IFeeManager feeManager = IFeeManager(address(verifier.s_feeManager()));
IRewardManager rewardManager = IRewardManager(address(feeManager.i_rewardManager()));
Expand All @@ -198,13 +230,19 @@ contract StreamsUpkeepRegistrar is ILogAutomation, StreamsLookupCompatibleInterf
// Verify the report
bytes memory verifiedReportData = verifier.verify(unverifiedReport, abi.encode(feeTokenAddress));

// Decode verified report data into a Report struct
Report memory verifiedReport = abi.decode(verifiedReportData, (Report));
// Decode verified report data into the appropriate Report struct based on reportVersion
if (reportVersion == 3) {
// v3 report schema
ReportV3 memory verifiedReport = abi.decode(verifiedReportData, (ReportV3));

// Log price from report
emit PriceUpdate(verifiedReport.price);
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
} else if (reportVersion == 4) {
// v4 report schema
ReportV4 memory verifiedReport = abi.decode(verifiedReportData, (ReportV4));

// Store the price from the report
s_last_retrieved_price = verifiedReport.price;
// Store the price from the report
lastDecodedPrice = verifiedReport.price;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ task("getLastRetrievedPrice", "Gets the last retrieved price from StreamsUpkeep"

try {
// Call the automatically generated getter function for the last_retrieved_price public state variable.
const s_lastRetrievedPrice = await StreamsUpkeepContract.s_last_retrieved_price()
spinner.succeed(`Last Retrieved Price: ${s_lastRetrievedPrice}`) // Display the retrieved price and stop the spinner with a success message.
const lastDecodedPrice = await StreamsUpkeepContract.lastDecodedPrice()
spinner.succeed(`Last Retrieved Price: ${lastDecodedPrice}`) // Display the retrieved price and stop the spinner with a success message.
} catch (error) {
spinner.fail("Failed to retrieve the last price.") // In case of error, stop the spinner with a failure message.
throw error
Expand Down
Loading