diff --git a/public/changelog.json b/public/changelog.json index 34d7a3e2b63..3d17e27ba35 100644 --- a/public/changelog.json +++ b/public/changelog.json @@ -1883,6 +1883,1118 @@ "title": "Cross-chain token (CCT) standard: Added support for new tokens", "topic": "CCIP" }, + { + "category": "integration", + "date": "2026-03-15", + "description": "New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):", + "relatedNetworks": [ + "0g", + "apechain", + "adi", + "aptos", + "arbitrum", + "arc", + "avalanche", + "base", + "berachain", + "bitlayer", + "blast", + "bnb-chain", + "bob", + "botanix", + "celo", + "dogeos", + "ethereum", + "giwa", + "gnosis-chain", + "gravity", + "hashkey", + "hedera", + "hyperliquid", + "injective", + "ink", + "jovay", + "katana", + "lens", + "linea", + "mantle", + "metis", + "monad", + "opbnb", + "optimism", + "polygon", + "perennial", + "pharos", + "plasma", + "ronin", + "scroll", + "shibarium", + "sei", + "seismic", + "soneium", + "sonic", + "solana", + "stable", + "xlayer", + "taiko", + "unichain", + "worldchain", + "zksync" + ], + "relatedTokens": [ + { + "assetName": "ADI Token", + "baseAsset": "ADI", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/adi-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/adi.webp" + }, + { + "assetName": "Oklo Inc", + "baseAsset": "OKLO", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/oklo-usd-overnighthoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/oklo.webp" + }, + { + "assetName": "Oklo Inc", + "baseAsset": "OKLO", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/oklo-usd-regularhoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/oklo.webp" + }, + { + "assetName": "Oklo Inc", + "baseAsset": "OKLO", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/oklo-usd-extendedhoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/oklo.webp" + }, + { + "assetName": "OpenDelta NX8", + "baseAsset": "NX8", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/nx8-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/nx8.webp" + }, + { + "assetName": "SanDisk Corp", + "baseAsset": "SNDK", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/sndk-usd-regularhoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sndk.webp" + }, + { + "assetName": "SanDisk Corp", + "baseAsset": "SNDK", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/sndk-usd-extendedhoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sndk.webp" + }, + { + "assetName": "SanDisk Corp", + "baseAsset": "SNDK", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/sndk-usd-overnighthoursequityprice-streams", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sndk.webp" + }, + { + "assetName": "Strategy Variable Rate Perpetual xStock", + "baseAsset": "STRCx", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/strcx-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/strcx.webp" + }, + { + "assetName": "Tessera tKalshi", + "baseAsset": "tKalshi", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/tkalshi-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/tkalshi.webp" + }, + { + "assetName": "Tessera tSpaceX", + "baseAsset": "tSpaceX", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/tspacex-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/tspacex.webp" + }, + { + "assetName": "Unitas USDu", + "baseAsset": "USDu", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/usdu-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdu.webp" + } + ], + "title": "Added support to Data Streams", + "topic": "Data Streams" + }, + { + "category": "integration", + "date": "2026-03-15", + "description": "New SmartData Feeds available:", + "relatedNetworks": ["ethereum"], + "relatedTokens": [ + { + "assetName": "Treasury+", + "baseAsset": "Treasury+", + "network": "ethereum", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/ethereum/mainnet/treasuryplus-nav", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/treasury+.webp" + } + ], + "title": "Added support to SmartData", + "topic": "SmartData" + }, + { + "category": "integration", + "date": "2026-03-15", + "description": "New Data Feeds available:", + "relatedNetworks": ["ethereum", "tron", "bnb-chain", "sonic"], + "relatedTokens": [ + { + "assetName": "AUSD", + "baseAsset": "AUSD", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/ausd-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/ausd.webp" + }, + { + "assetName": "HTX DAO", + "baseAsset": "HTX", + "quoteAsset": "USD", + "network": "tron", + "url": "https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&network=tron&search=htx", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/htx.webp" + }, + { + "assetName": "RLP / USD Exchange Rate", + "baseAsset": "RLP", + "quoteAsset": "USD", + "network": "bnb-chain", + "url": "https://data.chain.link/feeds/bsc/mainnet/rlp-usd-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/rlp.webp" + }, + { + "assetName": "stGLD / tGLD Exchange Rate", + "baseAsset": "stGLD", + "quoteAsset": "tGLD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/stgld-tgld-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/stgld.webp" + }, + { + "assetName": "sUSDD / USDD Exchange Rate", + "baseAsset": "sUSDD", + "quoteAsset": "sUSDD", + "network": "tron", + "url": "https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&network=tron&search=susdd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/susdd.webp" + }, + { + "assetName": "US Sonic Dollar", + "baseAsset": "USSD", + "quoteAsset": "USD", + "network": "sonic", + "url": "https://data.chain.link/feeds/sonic/sonic/ussd-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/ussd.webp" + }, + { + "assetName": "USDD / USDC Exchange Rate", + "baseAsset": "USDD", + "quoteAsset": "USDC", + "network": "tron", + "url": "https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&network=tron&search=usdd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdd.webp" + }, + { + "assetName": "USDD / USDT Exchange Rate", + "baseAsset": "USDD", + "quoteAsset": "USDT", + "network": "tron", + "url": "https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&network=tron&search=usdd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdd.webp" + }, + { + "assetName": "Wrapped Bitcoin", + "baseAsset": "WBTC", + "quoteAsset": "USD", + "network": "tron", + "url": "https://docs.chain.link/data-feeds/price-feeds/addresses?page=1&network=tron&search=wbtc", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/wbtc.webp" + } + ], + "title": "Added support to Data Feeds", + "topic": "Data Feeds" + }, + { + "category": "integration", + "date": "2026-03-13", + "description": "Chainlink CCIP expands support to new networks:", + "newNetworks": [ + { + "displayName": "Robinhood Chain Testnet", + "network": "robinhood", + "url": "https://docs.chain.link/ccip/directory/testnet/chain/robinhood-testnet" + }, + { + "displayName": "Ronin Saigon Testnet", + "network": "ronin", + "url": "https://docs.chain.link/ccip/directory/testnet/chain/ronin-testnet-saigon" + } + ], + "relatedNetworks": ["robinhood", "ronin"], + "title": "CCIP on Robinhood Chain Testnet and Ronin Saigon Testnet", + "topic": "CCIP" + }, + { + "category": "integration", + "date": "2026-03-08", + "description": "New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):", + "relatedNetworks": [ + "0g", + "apechain", + "adi-network", + "aptos", + "arbitrum", + "arc", + "avalanche", + "base", + "berachain", + "bitlayer", + "blast", + "bnb-chain", + "bob", + "botanix", + "celo", + "dogeos", + "ethereum", + "giwa", + "gnosis-chain", + "gravity", + "hashkey", + "hedera", + "hyperliquid", + "injective", + "ink", + "jovay", + "katana", + "lens", + "linea", + "mantle", + "metis", + "monad", + "opbnb", + "optimism", + "polygon", + "perennial", + "pharos", + "plasma", + "ronin", + "scroll", + "shibarium", + "sei", + "seismic", + "soneium", + "sonic", + "solana", + "stable", + "xlayer", + "taiko", + "unichain", + "worldchain", + "zksync" + ], + "relatedTokens": [ + { + "assetName": "DeFi Janus Henderson Anemoy AAA CLO Fund", + "baseAsset": "deJAAA", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/dejaaa-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/dejaaa.webp" + }, + { + "assetName": "DeFi Janus Henderson Anemoy Treasury Fund", + "baseAsset": "deJTRSY", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/dejtrsy-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/dejtrsy.webp" + }, + { + "assetName": "Saakuru", + "baseAsset": "SKR", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/skr-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/skr.webp" + } + ], + "title": "Added support to Data Streams", + "topic": "Data Streams" + }, + { + "category": "integration", + "date": "2026-03-08", + "description": "New Data Feeds available:", + "relatedNetworks": ["ethereum", "unichain", "xlayer"], + "relatedTokens": [ + { + "assetName": "Alphabet Inc - A", + "baseAsset": "GOOGL", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/googl-usd-kalman-24-5", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/googl.webp" + }, + { + "assetName": "Bitcoin", + "baseAsset": "BTC", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/btc-usd-svr", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/btc.webp" + }, + { + "assetName": "Chainlink", + "baseAsset": "LINK", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/link-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/link.webp" + }, + { + "assetName": "Circle USD", + "baseAsset": "USDC", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/usdc-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdc.webp" + }, + { + "assetName": "Circle USD", + "baseAsset": "USDC", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/usdc-usd-svr", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdc.webp" + }, + { + "assetName": "Ethereum", + "baseAsset": "ETH", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/eth-usd-svr", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/eth.webp" + }, + { + "assetName": "Invesco QQQ", + "baseAsset": "QQQ", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/qqq-usd-kalman-24-5", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/qqq.webp" + }, + { + "assetName": "Kelp DAO Restaked ETH", + "baseAsset": "RSETH", + "quoteAsset": "ETH", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/rseth-eth-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/rseth.webp" + }, + { + "assetName": "NVIDIA Corporation", + "baseAsset": "NVDA", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/nvda-usd-kalman-24-5", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/nvda.webp" + }, + { + "assetName": "Renzo Restaked ETH", + "baseAsset": "EZETH", + "quoteAsset": "ETH", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/ezeth-eth-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/ezeth.webp" + }, + { + "assetName": "Solana", + "baseAsset": "SOL", + "quoteAsset": "USD", + "network": "xlayer", + "url": "https://data.chain.link/feeds/xlayer/xlayer/sol-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sol.webp" + }, + { + "assetName": "SPDR S&P 500 ETF", + "baseAsset": "SPY", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/spy-usd-kalman-24-5", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/spy.webp" + }, + { + "assetName": "Tesla Inc", + "baseAsset": "TSLA", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/tsla-usd-kalman-24-5", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/tsla.webp" + }, + { + "assetName": "Uniswap", + "baseAsset": "UNI", + "quoteAsset": "USD", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/uni-usd-svr", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/uni.webp" + }, + { + "assetName": "Wrapped eETH", + "baseAsset": "weETH", + "quoteAsset": "eETH", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/weeth-eeth-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/weeth.webp" + }, + { + "assetName": "wstETH / stETH Exchange Rate", + "baseAsset": "wstETH", + "quoteAsset": "stETH", + "network": "unichain", + "url": "https://data.chain.link/feeds/unichain/mainnet/wsteth-steth-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/wsteth.webp" + } + ], + "title": "Added support to Data Feeds", + "topic": "Data Feeds" + }, + { + "category": "integration", + "date": "2026-03-08", + "description": "Newly supported tokens: ZYPTO, cbBTC", + "relatedTokens": [ + { + "assetName": "Zypto Token", + "baseAsset": "ZYPTO", + "url": "https://docs.chain.link/ccip/directory/mainnet/token/ZYPTO", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/zypto.webp?auto=compress%2Cformat&q=60&w=40&h=40&fit=cover" + }, + { + "assetName": "Coinbase Wrapped BTC", + "baseAsset": "cbBTC", + "url": "https://docs.chain.link/ccip/directory/mainnet/token/cbBTC", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/cbbtc.webp?auto=compress%2Cformat&q=60&w=40&h=40&fit=cover" + } + ], + "title": "Cross-chain token (CCT) standard: Added support for new tokens", + "topic": "CCIP" + }, + { + "category": "integration", + "date": "2026-03-06", + "description": "Chainlink CCIP expands support to new networks:", + "newNetworks": [ + { + "displayName": "ADI Network Mainnet", + "network": "adi-network", + "url": "https://docs.chain.link/ccip/directory/mainnet/chain/adi-network-mainnet" + }, + { + "displayName": "Edge Mainnet", + "network": "edge-mainnet", + "url": "https://docs.chain.link/ccip/directory/mainnet/chain/edge-mainnet" + }, + { + "displayName": "Edge Testnet", + "network": "edge-testnet", + "url": "https://docs.chain.link/ccip/directory/testnet/chain/edge-testnet" + } + ], + "relatedNetworks": ["adi-network", "edge"], + "title": "CCIP on ADI Network Mainnet, Edge Mainnet and Edge Testnet", + "topic": "CCIP" + }, + { + "category": "integration", + "date": "2026-03-06", + "description": "Newly supported tokens: ZYPTO", + "relatedTokens": [ + { + "assetName": "ZYPTO", + "baseAsset": "ZYPTO", + "url": "https://docs.chain.link/ccip/directory/mainnet/token/ZYPTO", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/zypto.webp?auto=compress%2Cformat&q=60&w=40&h=40&fit=cover" + } + ], + "title": "Cross-chain token (CCT) standard: Added support for new tokens", + "topic": "CCIP" + }, + { + "category": "release", + "date": "2026-03-05", + "description": "CLI version 1.3.0 adds TypeScript EVM binding generation, explicit `--target` prompting, Jovay/Pharos/XLayer mainnet support, and Pharos Atlantic testnet support.\n\n[See all changes on GitHub](https://github.com/smartcontractkit/cre-cli/compare/v1.2.0...v1.3.0)", + "title": "CRE CLI v1.3.0 — TypeScript Bindings and New Networks", + "topic": "CRE" + }, + { + "category": "release", + "date": "2026-03-05", + "description": "Go SDK version 1.5.0 adds Pharos Atlantic network support.\n\n[See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-go/compare/v1.4.0...v1.5.0)", + "title": "CRE Go SDK v1.5.0 — Pharos Atlantic Support", + "topic": "CRE" + }, + { + "category": "integration", + "date": "2026-03-03", + "description": "Chainlink Data Feeds is available on Unichain Mainnet. View the available price feed information on the [Price Feed Addresses](https://docs.chain.link/data-feeds/price-feeds/addresses?network=unichain&page=1) page.", + "relatedNetworks": ["unichain"], + "title": "Data Feeds Expands to Unichain Mainnet", + "topic": "Data Feeds" + }, + { + "category": "release", + "date": "2026-03-02", + "description": "Go SDK version 1.4.0 adds Solana LogTrigger SDK generation and Solana workflow bindings, and expands network support to Jovay Testnet, Pharos Testnet, and XLayer. Note: previously generated Solana SDK types have been removed and replaced by the new Solana bindings.\n\n[See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-go/compare/v1.3.0...v1.4.0)", + "title": "CRE Go SDK v1.4.0 — Solana Bindings and New Networks", + "topic": "CRE" + }, + { + "category": "release", + "date": "2026-03-02", + "description": "The CCIP SDK, CLI, and REST API are now generally available:\n\n- **CCIP SDK v1.0** ([@chainlink/ccip-sdk](https://www.npmjs.com/package/@chainlink/ccip-sdk)): Programmatic tools for sending messages, transferring tokens, estimating fees, and querying CCIP activity.\n- **CCIP CLI v1.0** ([@chainlink/ccip-cli](https://www.npmjs.com/package/@chainlink/ccip-cli)): Command-line interface for the same capabilities.\n- **CCIP API v2** ([REST API](https://docs.chain.link/ccip/tools/api/)): Endpoints for messages and their details, lane latency, and intents.\n\nSee the [CCIP Tools](https://docs.chain.link/ccip/tools/) documentation for details.", + "title": "CCIP SDK v1.0, CLI v1.0, and API v2", + "topic": "CCIP" + }, + { + "category": "integration", + "date": "2026-03-01", + "description": "New Data Streams available on all [supported networks](https://docs.chain.link/data-streams/crypto-streams):", + "relatedNetworks": [ + "0g", + "apechain", + "adi-network", + "aptos", + "arbitrum", + "arc", + "avalanche", + "base", + "berachain", + "bitlayer", + "blast", + "bnb-chain", + "bob", + "botanix", + "celo", + "dogeos", + "ethereum", + "gnosis-chain", + "gravity", + "hashkey", + "hedera", + "hyperliquid", + "injective", + "ink", + "jovay", + "katana", + "lens", + "linea", + "mantle", + "metis", + "monad", + "opbnb", + "optimism", + "polygon", + "perennial", + "pharos", + "plasma", + "ronin", + "scroll", + "shibarium", + "sei", + "soneium", + "sonic", + "solana", + "stable", + "taiko", + "unichain", + "worldchain", + "zksync" + ], + "relatedTokens": [ + { + "assetName": " Rocket Lab Corp", + "baseAsset": "RKLB", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/rklb-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/rklb.webp" + }, + { + "assetName": "Advanced Micro Devices / AMD", + "baseAsset": "AMD", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/amd-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/amd.webp" + }, + { + "assetName": "Alibaba Group Holding Ltd (ADRs)", + "baseAsset": "BABA", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/baba-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/baba.webp" + }, + { + "assetName": "Beyond Meat Inc", + "baseAsset": "BYND", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/bynd-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/bynd.webp" + }, + { + "assetName": "CoreWeave Inc", + "baseAsset": "CRWV", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/crwv-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/crwv.webp" + }, + { + "assetName": "DeFi Janus Henderson Anemoy AAA CLO Fund", + "baseAsset": "deJAAA", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/dejaaa-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/dejaaa.webp" + }, + { + "assetName": "DeFi Janus Henderson Anemoy Treasury Fund", + "baseAsset": "deJTRSY", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/dejtrsy-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/dejtrsy.webp" + }, + { + "assetName": "Global Dollar", + "baseAsset": "USDG", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/usdg-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdg.webp" + }, + { + "assetName": "Global X AI & Tech ETF", + "baseAsset": "AIQ", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/aiq-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/aiq.webp" + }, + { + "assetName": "Global X Robotics & Artificial Intelligence (BOTZ)", + "baseAsset": "BOTZ", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/botz-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/botz.webp" + }, + { + "assetName": "Intel Corp", + "baseAsset": "INTC", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/intc-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/intc.webp" + }, + { + "assetName": "iPath Series B S&P 500 VIX Short-Term Futures ETF", + "baseAsset": "VXX", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/vxx-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/vxx.webp" + }, + { + "assetName": "iShares 20+ Year Treasury Bond ETF", + "baseAsset": "TLT", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/tlt-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/tlt.webp" + }, + { + "assetName": "iShares Core MSCI Emerging Mkts ETF", + "baseAsset": "IEMG", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/iemg-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/iemg.webp" + }, + { + "assetName": "iShares Gold Trust", + "baseAsset": "IAU", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/iau-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/iau.webp" + }, + { + "assetName": "iShares MSCI Japan ETF", + "baseAsset": "EWJ", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/ewj-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/ewj.webp" + }, + { + "assetName": "iShares Russell 2000 ETF", + "baseAsset": "IWM", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/iwm-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/iwm.webp" + }, + { + "assetName": "iShares Silver Trust ETF", + "baseAsset": "SLV", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/slv-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/slv.webp" + }, + { + "assetName": "Kraneshares CSI China Internet ETF", + "baseAsset": "KWEB", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/kweb-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/kweb.webp" + }, + { + "assetName": "Micron Technology Inc", + "baseAsset": "MU", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/mu-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/mu.webp" + }, + { + "assetName": "Nebius Group", + "baseAsset": "NBIS", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/nbis-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/nbis.webp" + }, + { + "assetName": "Real Estate Select Sector SPDR Fund ETF", + "baseAsset": "XLRE", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/xlre-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/xlre.webp" + }, + { + "assetName": "Rigetti Computing Inc", + "baseAsset": "RGTI", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/rgti-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/rgti.webp" + }, + { + "assetName": "Roundhill Magnificent Seven ETF", + "baseAsset": "MAGS", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/mags-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/mags.webp" + }, + { + "assetName": "Schwab US REIT", + "baseAsset": "SCHH", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/schh-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/schh.webp" + }, + { + "assetName": "Sentient", + "baseAsset": "SENT", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/sent-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sent.webp" + }, + { + "assetName": "SPDR DJIA ETF", + "baseAsset": "DIA", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/dia-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/dia.webp" + }, + { + "assetName": "STRC", + "baseAsset": "STRC", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/strc-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/strc.webp" + }, + { + "assetName": "TSMC / Taiwan Semiconductor Man Co (ADRs)", + "baseAsset": "TSM", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/tsm-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/tsm.webp" + }, + { + "assetName": "United States Oil Fund LP ETF", + "baseAsset": "USO", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/uso-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/uso.webp" + }, + { + "assetName": "USD", + "baseAsset": "USD", + "quoteAsset": "ARS", + "url": "https://data.chain.link/streams/usd-ars", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usd.webp" + }, + { + "assetName": "USX / USD Redemption Rate", + "baseAsset": "USX", + "quoteAsset": "USD", + "url": "https://data.chain.link/streams/usx-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usx.webp" + } + ], + "title": "Added support to Data Streams", + "topic": "Data Streams" + }, + { + "category": "integration", + "date": "2026-03-01", + "description": "New SmartData Feeds available:", + "relatedNetworks": ["ethereum", "bnb-chain"], + "relatedTokens": [ + { + "assetName": "CRDYX NAV", + "baseAsset": "CRDYX", + "network": "ethereum", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/ethereum/mainnet/crdyx-nav", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/crdyx.webp" + }, + { + "assetName": "JAAA NAV", + "baseAsset": "JAAA", + "network": "ethereum", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/ethereum/mainnet/jaaa-nav-v2", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/jaaa.webp" + }, + { + "assetName": "JTRSY NAV", + "baseAsset": "JTRSY", + "network": "ethereum", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/ethereum/mainnet/jtrsy-nav-v2", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/jtrsy.webp" + }, + { + "assetName": "Kinesis Gold (KAU)", + "baseAsset": "KAU", + "network": "ethereum", + "productTypeCode": "PoR", + "url": "https://data.chain.link/feeds/ethereum/mainnet/kau-por", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/kau.webp" + }, + { + "assetName": "Kinesis Silver (KAG)", + "baseAsset": "KAG", + "network": "ethereum", + "productTypeCode": "PoR", + "url": "https://data.chain.link/feeds/ethereum/mainnet/kag-por", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/kag.webp" + }, + { + "assetName": "Renzo Restaked ETH", + "baseAsset": "ezETH", + "network": "ethereum", + "productTypeCode": "PoR", + "url": "https://data.chain.link/feeds/ethereum/mainnet/ezeth-por", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/ezeth.webp" + }, + { + "assetName": "US Dollar (USD) total reserves", + "baseAsset": "C1USD", + "network": "ethereum", + "productTypeCode": "PoR", + "url": "https://data.chain.link/feeds/ethereum/mainnet/c1usd-por", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/c1usd.webp" + }, + { + "assetName": "WTGXX NAV", + "baseAsset": "WTGXX", + "network": "ethereum", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/ethereum/mainnet/wtgxx-nav-24h", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/wtgxx.webp" + }, + { + "assetName": "XAUM Reference Rate", + "baseAsset": "XAUM", + "network": "bnb-chain", + "productTypeCode": "NAV", + "url": "https://data.chain.link/feeds/bsc/mainnet/xaum-reference-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/xaum.webp" + } + ], + "title": "Added support to SmartData", + "topic": "SmartData" + }, + { + "category": "integration", + "date": "2026-03-01", + "description": "New Data Feeds available:", + "relatedNetworks": ["arbitrum", "scroll", "base", "polygonkatana", "optimism", "ethereum"], + "relatedTokens": [ + { + "assetName": "Avant Staked USD", + "baseAsset": "savUSD", + "quoteAsset": "avUSD", + "network": "arbitrum", + "url": "https://data.chain.link/feeds/arbitrum/mainnet/savusd-avusd-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/savusd.webp" + }, + { + "assetName": "Circle EUR", + "baseAsset": "EURC", + "quoteAsset": "USD", + "network": "scroll", + "url": "https://data.chain.link/feeds/scroll/mainnet/eurc-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/eurc.webp" + }, + { + "assetName": "Ripple USD", + "baseAsset": "RLUSD", + "quoteAsset": "USD", + "network": "base", + "url": "https://data.chain.link/feeds/base/base/rlusd-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/rlusd.webp" + }, + { + "assetName": "Silver", + "baseAsset": "XAG", + "quoteAsset": "USD", + "network": "base", + "url": "https://data.chain.link/feeds/base/base/xag-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/xag.webp" + }, + { + "assetName": "Solv Protocol SOLVBTC / BTC Exchange Rate", + "baseAsset": "SOLVBTC", + "quoteAsset": "BTC", + "network": "arbitrum", + "url": "https://data.chain.link/feeds/arbitrum/mainnet/solvbtc-btc-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/solvbtc.webp" + }, + { + "assetName": "SUSDA / USDA Exchange Rate", + "baseAsset": "SUSDA", + "quoteAsset": "USDA", + "network": "polygonkatana", + "url": "https://data.chain.link/feeds/katana/polygon-mainnet-katana/susda-usda-exchange-rate", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/susda.webp" + }, + { + "assetName": "UMA", + "baseAsset": "UMA", + "quoteAsset": "USD", + "network": "optimism", + "url": "https://data.chain.link/feeds/optimism/mainnet/uma-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/uma.webp" + }, + { + "assetName": "Zcash", + "baseAsset": "ZEC", + "quoteAsset": "USD", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/zec-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/zec.webp" + }, + { + "assetName": "ZCash", + "baseAsset": "ZEC", + "quoteAsset": "USD", + "network": "arbitrum", + "url": "https://data.chain.link/feeds/arbitrum/mainnet/zec-usd", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/zec.webp" + } + ], + "title": "Added support to Data Feeds", + "topic": "Data Feeds" + }, + { + "category": "integration", + "date": "2026-02-26", + "description": "Chainlink Data Streams is available for new blockchains:\n\n- Giwa Sepolia Testnet\n- Injective EVM Testnet\n- Seismic Testnet\n- X Layer Mainnet\n- X Layer Testnet\n\nThe verifier proxy addresses and stream IDs are available on the [Stream Addresses](https://docs.chain.link/data-streams/crypto-streams) page.", + "relatedNetworks": ["giwa", "injective", "seismic", "xlayer"], + "title": "Data Streams Expands to New Blockchains", + "topic": "Data Streams" + }, + { + "category": "deprecation", + "date": "2026-02-26", + "description": "We have announced the deprecation of select Data Feeds, scheduled for shutdown on March 12th, 2026. Check [the list of Deprecating Data Feeds to learn more](https://docs.chain.link/data-feeds/deprecating-feeds).", + "title": "Deprecating Data Feeds", + "topic": "Data Feeds" + }, + { + "category": "release", + "date": "2026-02-26", + "description": "CRE CLI version 1.2.0 is now available. This release adds dynamic template fetching, new `cre templates` commands for managing template sources, and a new `cre account access` command for checking and requesting deployment access.\n\nUpdate your CLI by running `cre update` when prompted, or follow the [CLI Installation guide](https://docs.chain.link/cre/getting-started/cli-installation) for fresh installations.\n\n[See all changes on GitHub](https://github.com/smartcontractkit/cre-cli/compare/v1.1.0...v1.2.0)", + "title": "CRE CLI v1.2.0 — Dynamic Templates and Deploy Access Management", + "topic": "CRE" + }, + { + "category": "release", + "date": "2026-02-25", + "description": "CRE now supports the Confidential HTTP capability for production workflows, allowing you to make privacy-preserving API calls with enclave execution. See the [Confidential HTTP](https://docs.chain.link/cre/capabilities/confidential-http) page for more information.", + "title": "CRE supports Confidential HTTP capability for production workflows", + "topic": "CRE" + }, + { + "category": "integration", + "date": "2026-02-25", + "description": "Chainlink Data Streams is available for Canton. See the [Canton Integration](https://docs.chain.link/data-streams/canton-integration) page for more information.", + "relatedNetworks": ["canton"], + "title": "Data Streams Expands to Canton", + "topic": "Data Streams" + }, + { + "category": "integration", + "date": "2026-02-22", + "description": "New Data Feeds available:", + "relatedNetworks": ["ethereum", "arbitrum"], + "relatedTokens": [ + { + "assetName": "Swell Ethereum", + "baseAsset": "SWETH", + "quoteAsset": "ETH", + "network": "ethereum", + "url": "https://data.chain.link/feeds/ethereum/mainnet/sweth-eth", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sweth.webp" + }, + { + "assetName": "Swell Ethereum", + "baseAsset": "SWETH", + "quoteAsset": "ETH", + "network": "arbitrum", + "url": "https://data.chain.link/feeds/arbitrum/mainnet/sweth-eth", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/sweth.webp" + } + ], + "title": "Added support to Data Feeds", + "topic": "Data Feeds" + }, + { + "category": "integration", + "date": "2026-02-22", + "description": "Newly supported tokens: USDi", + "relatedTokens": [ + { + "assetName": "USDi Coin", + "baseAsset": "USDi", + "url": "https://docs.chain.link/ccip/directory/mainnet/token/USDi", + "iconUrl": "https://d2f70xi62kby8n.cloudfront.net/tokens/usdi.webp?auto=compress%2Cformat&q=60&w=40&h=40&fit=cover" + } + ], + "title": "Cross-chain token (CCT) standard: Added support for new tokens", + "topic": "CCIP" + }, { "category": "integration", "date": "2026-02-19", diff --git a/public/images/cre/crosschain-replay-attack-vector-diagram.png b/public/images/cre/crosschain-replay-attack-vector-diagram.png new file mode 100644 index 00000000000..968fe330866 Binary files /dev/null and b/public/images/cre/crosschain-replay-attack-vector-diagram.png differ diff --git a/public/images/cre/same-chain-replay-on-failure.png b/public/images/cre/same-chain-replay-on-failure.png new file mode 100644 index 00000000000..a4e8ffaa18e Binary files /dev/null and b/public/images/cre/same-chain-replay-on-failure.png differ diff --git a/src/content/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts.mdx b/src/content/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts.mdx index f05c3f441e2..f4d3d8a7fd2 100644 --- a/src/content/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts.mdx +++ b/src/content/cre/guides/workflow/using-evm-client/onchain-write/building-consumer-contracts.mdx @@ -525,13 +525,170 @@ The deployment and configuration process involves these steps: While the `setForwarderAddress()` function allows updating to `address(0)`, this disables the critical security check and allows **anyone** to call your `onReport()` function with arbitrary data. The function emits a `SecurityWarning` event if you attempt this. Only use `address(0)` for testing if you fully understand the implications. -### Replay protection +### Replay attacks -The `KeystoneForwarder` contract includes built-in replay protection that prevents successful reports from being executed multiple times. By requiring the forwarder address at construction time, `ReceiverTemplate` ensures your consumer benefits from this protection automatically. +CRE reports carry DON signatures that any compatible `KeystoneForwarder` will accept. This creates two distinct replay vectors that workflow authors must explicitly protect against by embedding protective metadata in their report payloads and verifying it in their consumer contracts. + +#### Cross-chain replay + +**The risk**: While publishing a single signed report to multiple chains simultaneously enables patterns like [Proof of Reserve (PoR)](/data-feeds/smartdata#proof-of-reserve-feeds) or feed-style publish-once-post-many, it also means **anyone holding a valid report can replay it on any chain that recognizes the DON's signing keys**. + +The forwarder validates cryptographic signatures but those signatures do not commit to a specific chain—without additional protection in your consumer contract, a replayed report can land on an unintended chain. + + + +**The mitigation**: Embed the target chain selector in the report payload. The consumer contract decodes this value and rejects reports not intended for the current chain. Chain selectors are `uint64` identifiers used throughout the CRE platform to identify blockchain networks — see [Chain Selectors](/cre/reference/sdk/evm-client-ts#chain-selectors) for the full list of constants and the `ChainSelectorFromName` helper. + +**Workflow (embed chain selector in the report payload):** + +```go +// Define your report struct with a ChainSelector field. +// ChainSelector is a uint64 — the same type used when instantiating evm.Client. +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ChainSelector uint64 // Target chain — used by the consumer to reject cross-chain replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ChainSelector: config.ChainSelector, // e.g., 16015286601757825753 for Ethereum Sepolia +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (verify the embedded chain selector):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ChainRestrictedConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint64 public immutable i_expectedChainSelector; + + error UnexpectedChainSelector(uint64 received, uint64 expected); + + constructor( + address _forwarderAddress, + address _token, + uint64 _expectedChainSelector + ) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + i_expectedChainSelector = _expectedChainSelector; + } + + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint64 chainSelector) = abi.decode( + report, + (address, uint256, uint64) + ); + + if (chainSelector != i_expectedChainSelector) { + revert UnexpectedChainSelector(chainSelector, i_expectedChainSelector); + } + + i_token.transfer(recipient, amount); + } +} +``` + +#### Same-chain replay on failure + +**The risk**: While allowing failed deliveries to be retried without requiring a new signed report enables permissionless recovery from transient failures, it also means the forwarder does not mark reverted transmissions as used. + +**A malicious actor can exploit this window**: after your workflow has already reacted to a failure (for example, scheduled a corrective action), an attacker can replay the original signed report once conditions recover, causing double-execution. + + + +{/* prettier-ignore */} + + +**The mitigation**: Embed the scheduled execution timestamp in the report payload. The consumer contract stores the last accepted timestamp and rejects any report with a timestamp equal to or earlier than the stored value. Once a later execution has been accepted, earlier failed reports can never land. + +{/* prettier-ignore */} + + +**Workflow (embed scheduled execution timestamp in the report payload):** + +```go +// Use the trigger's scheduled slot time — deterministic across all DON nodes. +// Refer to the cron trigger reference for the exact field name on cron.Payload. +scheduledAt := trigger.ScheduledAt.Unix() + +// Define your report struct with a ScheduledAt field +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ScheduledAt *big.Int // Monotonic execution timestamp — used to reject stale replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ScheduledAt: big.NewInt(scheduledAt), +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (reject reports from earlier executions):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ScheduledPaymentConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint256 public s_lastAcceptedTimestamp; + + error ReportTooOld(uint256 reportTimestamp, uint256 lastAccepted); + + event PaymentProcessed(address indexed recipient, uint256 amount, uint256 scheduledAt); + + constructor(address _forwarderAddress, address _token) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + } + + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint256 scheduledAt) = abi.decode( + report, + (address, uint256, uint256) + ); + + if (scheduledAt <= s_lastAcceptedTimestamp) { + revert ReportTooOld(scheduledAt, s_lastAcceptedTimestamp); + } + + s_lastAcceptedTimestamp = scheduledAt; + + i_token.transfer(recipient, amount); + emit PaymentProcessed(recipient, amount, scheduledAt); + } +} +``` {/* prettier-ignore */} - +{/* prettier-ignore */} + + ### Step 3: Generate the signed report Convert the encoded data to base64 and generate a report: diff --git a/src/content/cre/llms-full-go.txt b/src/content/cre/llms-full-go.txt index 78c01a4cfb9..b426f7da5a0 100644 --- a/src/content/cre/llms-full-go.txt +++ b/src/content/cre/llms-full-go.txt @@ -3070,13 +3070,163 @@ The deployment and configuration process involves these steps: While the `setForwarderAddress()` function allows updating to `address(0)`, this disables the critical security check and allows **anyone** to call your `onReport()` function with arbitrary data. The function emits a `SecurityWarning` event if you attempt this. Only use `address(0)` for testing if you fully understand the implications. -### Replay protection +### Replay attacks + +CRE reports carry DON signatures that any compatible `KeystoneForwarder` will accept. This creates two distinct replay vectors that workflow authors must explicitly protect against by embedding protective metadata in their report payloads and verifying it in their consumer contracts. + +#### Cross-chain replay + +**The risk**: While publishing a single signed report to multiple chains simultaneously enables patterns like [Proof of Reserve (PoR)](/data-feeds/smartdata#proof-of-reserve-feeds) or feed-style publish-once-post-many, it also means **anyone holding a valid report can replay it on any chain that recognizes the DON's signing keys**. + +The forwarder validates cryptographic signatures but those signatures do not commit to a specific chain—without additional protection in your consumer contract, a replayed report can land on an unintended chain. + +**The mitigation**: Embed the target chain selector in the report payload. The consumer contract decodes this value and rejects reports not intended for the current chain. Chain selectors are `uint64` identifiers used throughout the CRE platform to identify blockchain networks — see [Chain Selectors](/cre/reference/sdk/evm-client-ts#chain-selectors) for the full list of constants and the `ChainSelectorFromName` helper. + +**Workflow (embed chain selector in the report payload):** + +```go +// Define your report struct with a ChainSelector field. +// ChainSelector is a uint64 — the same type used when instantiating evm.Client. +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ChainSelector uint64 // Target chain — used by the consumer to reject cross-chain replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ChainSelector: config.ChainSelector, // e.g., 16015286601757825753 for Ethereum Sepolia +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (verify the embedded chain selector):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ChainRestrictedConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint64 public immutable i_expectedChainSelector; + + error UnexpectedChainSelector(uint64 received, uint64 expected); + + constructor( + address _forwarderAddress, + address _token, + uint64 _expectedChainSelector + ) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + i_expectedChainSelector = _expectedChainSelector; + } + + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint64 chainSelector) = abi.decode( + report, + (address, uint256, uint64) + ); + + if (chainSelector != i_expectedChainSelector) { + revert UnexpectedChainSelector(chainSelector, i_expectedChainSelector); + } + + i_token.transfer(recipient, amount); + } +} +``` + +#### Same-chain replay on failure + +**The risk**: While allowing failed deliveries to be retried without requiring a new signed report enables permissionless recovery from transient failures, it also means the forwarder does not mark reverted transmissions as used. + +**A malicious actor can exploit this window**: after your workflow has already reacted to a failure (for example, scheduled a corrective action), an attacker can replay the original signed report once conditions recover, causing double-execution. + + + + +**The mitigation**: Embed the scheduled execution timestamp in the report payload. The consumer contract stores the last accepted timestamp and rejects any report with a timestamp equal to or earlier than the stored value. Once a later execution has been accepted, earlier failed reports can never land. + + + -The `KeystoneForwarder` contract includes built-in replay protection that prevents successful reports from being executed multiple times. By requiring the forwarder address at construction time, `ReceiverTemplate` ensures your consumer benefits from this protection automatically. +**Workflow (embed scheduled execution timestamp in the report payload):** +```go +// Use the trigger's scheduled slot time — deterministic across all DON nodes. +// Refer to the cron trigger reference for the exact field name on cron.Payload. +scheduledAt := trigger.ScheduledAt.Unix() + +// Define your report struct with a ScheduledAt field +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ScheduledAt *big.Int // Monotonic execution timestamp — used to reject stale replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ScheduledAt: big.NewInt(scheduledAt), +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (reject reports from earlier executions):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ScheduledPaymentConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint256 public s_lastAcceptedTimestamp; + + error ReportTooOld(uint256 reportTimestamp, uint256 lastAccepted); + + event PaymentProcessed(address indexed recipient, uint256 amount, uint256 scheduledAt); + + constructor(address _forwarderAddress, address _token) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + } + + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint256 scheduledAt) = abi.decode( + report, + (address, uint256, uint256) + ); + + if (scheduledAt <= s_lastAcceptedTimestamp) { + revert ReportTooOld(scheduledAt, s_lastAcceptedTimestamp); + } - -### Replay protection +### Replay attacks + +CRE reports carry DON signatures that any compatible `KeystoneForwarder` will accept. This creates two distinct replay vectors that workflow authors must explicitly protect against by embedding protective metadata in their report payloads and verifying it in their consumer contracts. + +#### Cross-chain replay + +**The risk**: While publishing a single signed report to multiple chains simultaneously enables patterns like [Proof of Reserve (PoR)](/data-feeds/smartdata#proof-of-reserve-feeds) or feed-style publish-once-post-many, it also means **anyone holding a valid report can replay it on any chain that recognizes the DON's signing keys**. + +The forwarder validates cryptographic signatures but those signatures do not commit to a specific chain—without additional protection in your consumer contract, a replayed report can land on an unintended chain. + +**The mitigation**: Embed the target chain selector in the report payload. The consumer contract decodes this value and rejects reports not intended for the current chain. Chain selectors are `uint64` identifiers used throughout the CRE platform to identify blockchain networks — see [Chain Selectors](/cre/reference/sdk/evm-client-ts#chain-selectors) for the full list of constants and the `ChainSelectorFromName` helper. + +**Workflow (embed chain selector in the report payload):** + +```go +// Define your report struct with a ChainSelector field. +// ChainSelector is a uint64 — the same type used when instantiating evm.Client. +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ChainSelector uint64 // Target chain — used by the consumer to reject cross-chain replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ChainSelector: config.ChainSelector, // e.g., 16015286601757825753 for Ethereum Sepolia +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (verify the embedded chain selector):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ChainRestrictedConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint64 public immutable i_expectedChainSelector; + + error UnexpectedChainSelector(uint64 received, uint64 expected); + + constructor( + address _forwarderAddress, + address _token, + uint64 _expectedChainSelector + ) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + i_expectedChainSelector = _expectedChainSelector; + } + + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint64 chainSelector) = abi.decode( + report, + (address, uint256, uint64) + ); + + if (chainSelector != i_expectedChainSelector) { + revert UnexpectedChainSelector(chainSelector, i_expectedChainSelector); + } + + i_token.transfer(recipient, amount); + } +} +``` + +#### Same-chain replay on failure + +**The risk**: While allowing failed deliveries to be retried without requiring a new signed report enables permissionless recovery from transient failures, it also means the forwarder does not mark reverted transmissions as used. + +**A malicious actor can exploit this window**: after your workflow has already reacted to a failure (for example, scheduled a corrective action), an attacker can replay the original signed report once conditions recover, causing double-execution. + + + + +**The mitigation**: Embed the scheduled execution timestamp in the report payload. The consumer contract stores the last accepted timestamp and rejects any report with a timestamp equal to or earlier than the stored value. Once a later execution has been accepted, earlier failed reports can never land. + + + + +**Workflow (embed scheduled execution timestamp in the report payload):** + +```go +// Use the trigger's scheduled slot time — deterministic across all DON nodes. +// Refer to the cron trigger reference for the exact field name on cron.Payload. +scheduledAt := trigger.ScheduledAt.Unix() + +// Define your report struct with a ScheduledAt field +type PaymentReport struct { + Recipient common.Address + Amount *big.Int + ScheduledAt *big.Int // Monotonic execution timestamp — used to reject stale replays +} + +paymentReport := PaymentReport{ + Recipient: common.HexToAddress(config.Recipient), + Amount: big.NewInt(100_000_000), // e.g., 100 USDC (6 decimals) + ScheduledAt: big.NewInt(scheduledAt), +} + +// ABI-encode paymentReport and pass to runtime.GenerateReport() as normal +``` + +**Consumer contract (reject reports from earlier executions):** + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { ReceiverTemplate } from "./ReceiverTemplate.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract ScheduledPaymentConsumer is ReceiverTemplate { + IERC20 public immutable i_token; + uint256 public s_lastAcceptedTimestamp; + + error ReportTooOld(uint256 reportTimestamp, uint256 lastAccepted); + + event PaymentProcessed(address indexed recipient, uint256 amount, uint256 scheduledAt); + + constructor(address _forwarderAddress, address _token) ReceiverTemplate(_forwarderAddress) { + i_token = IERC20(_token); + } -The `KeystoneForwarder` contract includes built-in replay protection that prevents successful reports from being executed multiple times. By requiring the forwarder address at construction time, `ReceiverTemplate` ensures your consumer benefits from this protection automatically. + function _processReport(bytes calldata report) internal override { + (address recipient, uint256 amount, uint256 scheduledAt) = abi.decode( + report, + (address, uint256, uint256) + ); + if (scheduledAt <= s_lastAcceptedTimestamp) { + revert ReportTooOld(scheduledAt, s_lastAcceptedTimestamp); + } - + + + ### Step 3: Generate the signed report Convert the encoded data to base64 and generate a report: